Merge branch 'master' into devel/merge-master-into-downstream-cookies

This commit is contained in:
Willem Toorop 2022-11-07 17:09:20 +00:00
commit 8df26b132b
84 changed files with 7313 additions and 5081 deletions

View File

@ -130,7 +130,7 @@ util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
util/rtt.c util/siphash.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
util/storage/lruhash.c util/storage/slabhash.c util/tcp_conn_limit.c \
util/timehist.c util/tube.c \
util/timehist.c util/tube.c util/proxy_protocol.c \
util/ub_event.c util/ub_event_pluggable.c util/winsock_event.c \
validator/autotrust.c validator/val_anchor.c validator/validator.c \
validator/val_kcache.c validator/val_kentry.c validator/val_neg.c \
@ -148,7 +148,7 @@ outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \
fptr_wlist.lo siphash.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
slabhash.lo tcp_conn_limit.lo timehist.lo tube.lo winsock_event.lo \
autotrust.lo val_anchor.lo rpz.lo \
autotrust.lo val_anchor.lo rpz.lo proxy_protocol.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo \
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
@ -985,6 +985,8 @@ netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/neteve
$(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)/sldns/str2wire.h \
$(srcdir)/dnstap/dnstap.h $(srcdir)/services/listen_dnsport.h
proxy_protocol.lo proxy_protocol.o: $(srcdir)/util/proxy_protocol.c config.h \
$(srcdir)/util/proxy_protocol.h $(srcdir)/sldns/sbuffer.h
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@ -1514,7 +1516,7 @@ asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libu
$(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/rrdef.h
streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/net_help.h $(srcdir)/util/proxy_protocol.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h

View File

@ -390,6 +390,15 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
if(!qstate->return_msg || !qstate->return_msg->rep)
return 0;
/* do not store failures like SERVFAIL in the cachedb, this avoids
* overwriting expired, valid, content with broken content. */
if(FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
LDNS_RCODE_NOERROR &&
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
LDNS_RCODE_NXDOMAIN &&
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
LDNS_RCODE_YXDOMAIN)
return 0;
/* We don't store the reply if its TTL is 0 unless serve-expired is
* enabled. Such a reply won't be reusable and simply be a waste for
* the backend. It's also compatible with the default behavior of

25
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for unbound 1.17.0.
# Generated by GNU Autoconf 2.69 for unbound 1.17.1.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
#
@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
PACKAGE_VERSION='1.17.0'
PACKAGE_STRING='unbound 1.17.0'
PACKAGE_VERSION='1.17.1'
PACKAGE_STRING='unbound 1.17.1'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL=''
@ -1477,7 +1477,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures unbound 1.17.0 to adapt to many kinds of systems.
\`configure' configures unbound 1.17.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1543,7 +1543,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of unbound 1.17.0:";;
short | recursive ) echo "Configuration of unbound 1.17.1:";;
esac
cat <<\_ACEOF
@ -1785,7 +1785,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
unbound configure 1.17.0
unbound configure 1.17.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2494,7 +2494,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by unbound $as_me 1.17.0, which was
It was created by unbound $as_me 1.17.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2846,11 +2846,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=17
UNBOUND_VERSION_MICRO=0
UNBOUND_VERSION_MICRO=1
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=20
LIBUNBOUND_REVISION=21
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@ -2938,6 +2938,7 @@ LIBUNBOUND_AGE=1
# 1.16.2 had 9:18:1
# 1.16.3 had 9:19:1
# 1.17.0 had 9:20:1
# 1.17.1 had 9:21:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@ -22085,7 +22086,7 @@ _ACEOF
version=1.17.0
version=1.17.1
date=`date +'%b %e, %Y'`
@ -22604,7 +22605,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by unbound $as_me 1.17.0, which was
This file was extended by unbound $as_me 1.17.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -22670,7 +22671,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
unbound config.status 1.17.0
unbound config.status 1.17.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -11,14 +11,14 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[17])
m4_define([VERSION_MICRO],[0])
m4_define([VERSION_MICRO],[1])
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=20
LIBUNBOUND_REVISION=21
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@ -106,6 +106,7 @@ LIBUNBOUND_AGE=1
# 1.16.2 had 9:18:1
# 1.16.3 had 9:19:1
# 1.17.0 had 9:20:1
# 1.17.1 had 9:21:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary

View File

@ -199,7 +199,7 @@ acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr,
/** apply acl_interface string */
static int
acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
acl_interface_str_cfg(struct acl_list* acl_interface, const char* iface,
const char* s2, int port)
{
struct acl_addr* node;
@ -207,9 +207,9 @@ acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
if(!parse_acl_access(s2, &control)) {
return 0;
}
if(!(node=acl_find_or_create_str2addr(acl_interface, interface, 1, port))) {
if(!(node=acl_find_or_create_str2addr(acl_interface, iface, 1, port))) {
log_err("cannot update ACL on non-configured interface: %s %d",
interface, port);
iface, port);
return 0;
}
node->control = control;

View File

@ -494,8 +494,8 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
n->c->do_not_close = 0;
comm_point_stop_listening(n->c);
comm_point_start_listening(n->c, -1, REMOTE_CONTROL_TCP_TIMEOUT);
memcpy(&n->c->repinfo.addr, &addr, addrlen);
n->c->repinfo.addrlen = addrlen;
memcpy(&n->c->repinfo.remote_addr, &addr, addrlen);
n->c->repinfo.remote_addrlen = addrlen;
if(rc->use_cert) {
n->shake_state = rc_hs_read;
n->ssl = SSL_new(rc->ctx);
@ -3304,7 +3304,7 @@ remote_handshake_later(struct daemon_remote* rc, struct rc_state* s,
if(r == 0)
log_err("remote control connection closed prematurely");
log_addr(VERB_OPS, "failed connection from",
&s->c->repinfo.addr, s->c->repinfo.addrlen);
&s->c->repinfo.remote_addr, s->c->repinfo.remote_addrlen);
log_crypto_err("remote control failed ssl");
clean_point(rc, s);
}

View File

@ -521,7 +521,7 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
stats->qhttps++;
}
}
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
stats->qipv6++;
if( (flags&BIT_QR) )
stats->qbit_QR++;

View File

@ -547,7 +547,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
static int
apply_respip_action(struct worker* worker, const struct query_info* qinfo,
struct respip_client_info* cinfo, struct reply_info* rep,
struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
struct sockaddr_storage* addr, socklen_t addrlen,
struct ub_packed_rrset_key** alias_rrset,
struct reply_info** encode_repp, struct auth_zones* az)
{
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
@ -574,7 +575,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
if(actinfo.addrinfo) {
respip_inform_print(&actinfo, qinfo->qname,
qinfo->qtype, qinfo->qclass, qinfo->local_alias,
repinfo);
addr, addrlen);
if(worker->stats.extended && actinfo.rpz_used) {
if(actinfo.rpz_disabled)
@ -703,7 +704,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
!partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
repinfo, alias_rrset,
&repinfo->client_addr, repinfo->client_addrlen, alias_rrset,
&encode_rep, worker->env.auth_zones)) {
goto bail_out;
} else if(partial_rep &&
@ -991,12 +992,14 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
* @param w: worker
* @param qinfo: query info. Pointer into packet buffer.
* @param edns: edns info from query.
* @param repinfo: reply info with source address.
* @param addr: client address.
* @param addrlen: client address length.
* @param pkt: packet buffer.
*/
static void
answer_notify(struct worker* w, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* pkt, struct comm_reply* repinfo)
answer_notify(struct worker* w, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* pkt,
struct sockaddr_storage* addr, socklen_t addrlen)
{
int refused = 0;
int rcode = LDNS_RCODE_NOERROR;
@ -1005,8 +1008,8 @@ answer_notify(struct worker* w, struct query_info* qinfo,
if(!w->env.auth_zones) return;
has_serial = auth_zone_parse_notify_serial(pkt, &serial);
if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname,
qinfo->qname_len, qinfo->qclass, &repinfo->addr,
repinfo->addrlen, has_serial, serial, &refused)) {
qinfo->qname_len, qinfo->qclass, addr,
addrlen, has_serial, serial, &refused)) {
rcode = LDNS_RCODE_NOERROR;
} else {
if(refused)
@ -1031,7 +1034,7 @@ answer_notify(struct worker* w, struct query_info* qinfo,
"servfail for NOTIFY %sfor %s from", sr, zname);
else snprintf(buf, sizeof(buf),
"received NOTIFY %sfor %s from", sr, zname);
log_addr(VERB_DETAIL, buf, &repinfo->addr, repinfo->addrlen);
log_addr(VERB_DETAIL, buf, addr, addrlen);
}
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
@ -1051,8 +1054,8 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
{
if(acl == deny) {
if(verbosity >= VERB_ALGO) {
log_acl_action("dropped", &repinfo->addr,
repinfo->addrlen, acl, acladdr);
log_acl_action("dropped", &repinfo->client_addr,
repinfo->client_addrlen, acl, acladdr);
log_buf(VERB_ALGO, "dropped", c->buffer);
}
comm_point_drop_reply(repinfo);
@ -1063,8 +1066,8 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
size_t opt_rr_mark;
if(verbosity >= VERB_ALGO) {
log_acl_action("refused", &repinfo->addr,
repinfo->addrlen, acl, acladdr);
log_acl_action("refused", &repinfo->client_addr,
repinfo->client_addrlen, acl, acladdr);
log_buf(VERB_ALGO, "refuse", c->buffer);
}
@ -1224,12 +1227,24 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
}
static int
deny_refuse_all(struct comm_point* c, enum acl_access acl,
deny_refuse_all(struct comm_point* c, enum acl_access* acl,
struct worker* worker, struct comm_reply* repinfo,
struct acl_addr* acladdr, int ede)
struct acl_addr** acladdr, int ede, int check_proxy)
{
return deny_refuse(c, acl, acl_deny, acl_refuse, worker, repinfo,
acladdr, ede);
if(check_proxy) {
*acladdr = acl_addr_lookup(worker->daemon->acl,
&repinfo->remote_addr, repinfo->remote_addrlen);
} else {
*acladdr = acl_addr_lookup(worker->daemon->acl,
&repinfo->client_addr, repinfo->client_addrlen);
}
/* If there is no ACL based on client IP use the interface ACL. */
if(!(*acladdr) && c->socket) {
*acladdr = c->socket->acl;
}
*acl = acl_get_control(*acladdr);
return deny_refuse(c, *acl, acl_deny, acl_refuse, worker, repinfo,
*acladdr, ede);
}
static int
@ -1241,7 +1256,7 @@ deny_refuse_non_local(struct comm_point* c, enum acl_access acl,
worker, repinfo, acladdr, ede);
}
int
int
worker_handle_request(struct comm_point* c, void* arg, int error,
struct comm_reply* repinfo)
{
@ -1286,16 +1301,16 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(worker_check_request(c->buffer, worker) != 0) {
verbose(VERB_ALGO,
"dnscrypt: worker check request: bad query.");
log_addr(VERB_CLIENT,"from",&repinfo->addr,
repinfo->addrlen);
log_addr(VERB_CLIENT,"from",&repinfo->client_addr,
repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
if(!query_info_parse(&qinfo, c->buffer)) {
verbose(VERB_ALGO,
"dnscrypt: worker parse request: formerror.");
log_addr(VERB_CLIENT, "from", &repinfo->addr,
repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
@ -1323,29 +1338,30 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* sending src (client)/dst (local service) addresses over DNSTAP from incoming request handler
*/
if(worker->dtenv.log_client_query_messages) {
log_addr(VERB_ALGO, "request from client", &repinfo->addr, repinfo->addrlen);
log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
}
#endif
acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr,
repinfo->addrlen);
/* If there is no ACL based on client IP use the interface ACL. */
if(!acladdr && c->socket) {
acladdr = c->socket->acl;
/* Check deny/refuse ACLs */
if(repinfo->is_proxied) {
if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr,
worker->env.cfg->ede, 1)) != -1) {
if(ret == 1)
goto send_reply;
return ret;
}
}
acl = acl_get_control(acladdr);
if((ret=deny_refuse_all(c, acl, worker, repinfo, acladdr,
worker->env.cfg->ede)) != -1)
{
if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr,
worker->env.cfg->ede, 0)) != -1) {
if(ret == 1)
goto send_reply;
return ret;
}
if((ret=worker_check_request(c->buffer, worker)) != 0) {
verbose(VERB_ALGO, "worker check request: bad query.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
if(ret != -1) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), ret);
@ -1357,20 +1373,24 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->stats.num_queries++;
/* check if this query should be dropped based on source ip rate limiting */
if(!infra_ip_ratelimit_inc(worker->env.infra_cache, repinfo,
/* check if this query should be dropped based on source ip rate limiting
* NOTE: we always check the repinfo->client_address. IP ratelimiting is
* implicitly disabled for proxies. */
if(!infra_ip_ratelimit_inc(worker->env.infra_cache,
&repinfo->client_addr, repinfo->client_addrlen,
*worker->env.now,
worker->env.cfg->ip_ratelimit_backoff, c->buffer)) {
/* See if we are passed through with slip factor */
if(worker->env.cfg->ip_ratelimit_factor != 0 &&
ub_random_max(worker->env.rnd,
worker->env.cfg->ip_ratelimit_factor) == 0) {
worker->env.cfg->ip_ratelimit_factor) == 0) {
char addrbuf[128];
addr_to_str(&repinfo->addr, repinfo->addrlen,
addrbuf, sizeof(addrbuf));
verbose(VERB_QUERY, "ip_ratelimit allowed through for ip address %s because of slip in ip_ratelimit_factor",
addrbuf);
addr_to_str(&repinfo->client_addr,
repinfo->client_addrlen, addrbuf,
sizeof(addrbuf));
verbose(VERB_QUERY, "ip_ratelimit allowed through for "
"ip address %s because of slip in "
"ip_ratelimit_factor", addrbuf);
} else {
worker->stats.num_queries_ip_ratelimited++;
comm_point_drop_reply(repinfo);
@ -1381,7 +1401,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/* see if query is in the cache */
if(!query_info_parse(&qinfo, c->buffer)) {
verbose(VERB_ALGO, "worker parse request: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
memset(&qinfo, 0, sizeof(qinfo)); /* zero qinfo.qname */
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
@ -1395,13 +1416,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if(worker->env.cfg->log_queries) {
char ip[128];
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
}
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
verbose(VERB_ALGO, "worker request: refused zone transfer.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
@ -1418,7 +1440,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
qinfo.qtype == LDNS_RR_TYPE_MAILB ||
(qinfo.qtype >= 128 && qinfo.qtype <= 248)) {
verbose(VERB_ALGO, "worker request: formerror for meta-type.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
return 0;
@ -1438,7 +1461,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->scratchpad)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
memset(&reply_edns, 0, sizeof(reply_edns));
reply_edns.edns_present = 1;
error_encode(c->buffer, ret, &qinfo,
@ -1453,7 +1477,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
verbose(VERB_ALGO, "query with bad edns version.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr( VERB_CLIENT, "from",&repinfo->remote_addr
, repinfo->remote_addrlen);
extended_error_encode(c->buffer, EDNS_RCODE_BADVERS, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), 0, &edns);
@ -1464,7 +1489,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->daemon->cfg->harden_short_bufsize) {
verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
(int)edns.udp_size);
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
edns.udp_size = NORMAL_UDP_SIZE;
}
}
@ -1492,8 +1518,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/* Cookie requered, but no cookie present on UDP */
verbose(VERB_ALGO, "worker request: "
"need cookie or stateful transport");
log_addr(VERB_ALGO, "from",
&repinfo->addr, repinfo->addrlen);
log_addr(VERB_ALGO, "from",&repinfo->remote_addr
, repinfo->remote_addrlen);
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
worker->scratchpad, LDNS_EDE_OTHER,
"DNS Cookie needed for UDP replies");
@ -1511,12 +1537,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_QUERY,
"worker request: max UDP reply size modified"
" (%d to max-udp-size)", (int)edns.udp_size);
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
edns.udp_size = worker->daemon->cfg->max_udp_size;
}
if(edns.udp_size < LDNS_HEADER_SIZE) {
verbose(VERB_ALGO, "worker request: edns is too small.");
log_addr(VERB_CLIENT, "from", &repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_TC_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
@ -1540,7 +1568,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if(LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ==
LDNS_PACKET_NOTIFY) {
answer_notify(worker, &qinfo, &edns, c->buffer, repinfo);
answer_notify(worker, &qinfo, &edns, c->buffer,
&repinfo->client_addr, repinfo->client_addrlen);
regional_free_all(worker->scratchpad);
goto send_reply;
}
@ -1616,7 +1645,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
sldns_buffer_read_u16_at(c->buffer, 2), &edns);
regional_free_all(worker->scratchpad);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
&repinfo->client_addr, repinfo->client_addrlen);
goto send_reply;
}
@ -1756,9 +1785,9 @@ lookup_cache:
if(verbosity >= VERB_CLIENT) {
if(c->type == comm_udp)
log_addr(VERB_CLIENT, "udp request from",
&repinfo->addr, repinfo->addrlen);
&repinfo->client_addr, repinfo->client_addrlen);
else log_addr(VERB_CLIENT, "tcp request from",
&repinfo->addr, repinfo->addrlen);
&repinfo->client_addr, repinfo->client_addrlen);
}
/* grab a work request structure for this new request */
@ -1790,8 +1819,8 @@ send_reply_rc:
*/
if(worker->dtenv.log_client_response_messages) {
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen);
dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
}
#endif
if(worker->env.cfg->log_replies)
@ -1803,10 +1832,12 @@ send_reply_rc:
/* log original qname, before the local alias was
* used to resolve that CNAME to something else */
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
log_reply_info(NO_VERBOSE, &qinfo, &repinfo->addr, repinfo->addrlen,
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer);
} else {
log_reply_info(NO_VERBOSE, &qinfo, &repinfo->addr, repinfo->addrlen,
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer);
}
}

View File

@ -1,3 +1,72 @@
21 October 2022: George
- Merge #767 from jonathangray: consistently use IPv4/IPv6 in
unbound.conf.5.
21 October 2022: Wouter
- Fix that cachedb does not store failures in the external cache.
18 October 2022: George
- Clarify the use of MAX_SENT_COUNT in the iterator code.
17 October 2022: Wouter
- testcode/dohclient sets log identity to its name.
14 October 2022: Wouter
- Merge #768 from fobser: Arithmetic on a pointer to void is a GNU
extension.
- In unit test, print python script name list correctly.
13 October 2022: Wouter
- Tag for 1.17.0 release. The code repository continues with 1.17.1.
11 October 2022: George
- Fix PROXYv2 header read for TCP connections when no proxied addresses
are provided.
7 October 2022: Wouter
- Tag for 1.17.0rc1 release.
7 October 2022: George
- Fix to stop possible loops in the tcp reuse code (write_wait list
and tcp_wait list). Based on analysis and patch from Prad Seniappan
and Karthik Umashankar.
- Fix unit test to properly test the reuse_write_wait_pop function.
6 October 2022: Wouter
- Fix to stop responses with TC flag from resulting in partial
responses. It retries to fetch the data elsewhere, or fails the
query and in depth fix removes the TC flag from the cached item.
- Fix proxy length debug output printout typecasts.
5 October 2022: Wouter
- Fix dnscrypt compile for proxy protocol code changes.
5 October 2022: George
- Use DEBUG_TDIR from environment in mini_tdir.sh for debugging.
- Fix string comparison in mini_tdir.sh.
- Make ede.tdir test more predictable by using static data.
- Fix checkconf test for dnscrypt and proxy port.
4 October 2022: George
- Merge #764: Leniency for target discovery when under load (for
NRDelegation changes).
4 October 2022: Wouter
- Fix static analysis report to remove dead code from the
rpz_callback_from_iterator_module function.
- Fix to clean up after the acl_interface unit test.
3 October 2022: George
- Merge #760: PROXYv2 downstream support. (New proxy-protocol-port
configuration option).
3 October 2022: Wouter
- Fix to remove erroneous TC flag from TCP upstream.
- Fix test tdir skip report printout.
- Fix windows compile, the identifier interface is defined in headers.
- Fix to close errno block in comm_point_tcp_handle_read outside of
ifdef.
26 September 2022: George
- Better output for skipped tdir tests.

View File

@ -902,6 +902,10 @@ server:
# Disable TLS for DNS-over-HTTP downstream service.
# http-notls-downstream: no
# The interfaces that use these listed port numbers will support and
# expect PROXYv2. For UDP and TCP/TLS interfaces.
# proxy-protocol-port: portno for each of the port numbers.
# DNS64 prefix. Must be specified when DNS64 is use.
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
# dns64-prefix: 64:ff9b::0/96

View File

@ -349,7 +349,7 @@ ip\-transparent option is also available.
The value of the Differentiated Services Codepoint (DSCP) in the
differentiated services field (DS) of the outgoing IP packet headers.
The field replaces the outdated IPv4 Type-Of-Service field and the
IPV6 traffic class field.
IPv6 traffic class field.
.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
@ -416,7 +416,7 @@ Enable or disable whether ip4 queries are answered or issued. Default is yes.
Enable or disable whether ip6 queries are answered or issued. Default is yes.
If disabled, queries are not answered on IPv6, and queries are not sent on
IPv6 to the internet nameservers. With this option you can disable the
ipv6 transport for sending DNS traffic, it does not impact the contents of
IPv6 transport for sending DNS traffic, it does not impact the contents of
the DNS traffic, which may have ip4 and ip6 addresses in it.
.TP
.B prefer\-ip4: \fI<yes or no>
@ -656,6 +656,17 @@ Ignored if the option is not available. Default is yes.
Disable use of TLS for the downstream DNS-over-HTTP connections. Useful for
local back end servers. Default is no.
.TP
.B proxy\-protocol\-port: \fI<portnr>
List port numbers as proxy\-protocol\-port, and when interfaces are defined,
eg. with the @port suffix, as this port number, they support and expect PROXYv2.
In this case the proxy address will only be used for the network communication
and initial ACL (check if the proxy itself is denied/refused by configuration).
The proxied address (if any) will then be used as the true client address and
will be used where applicable for logging, ACL, DNSTAP, RPZ and IP ratelimiting.
PROXYv2 is supported for UDP and TCP/TLS listening interfaces.
There is no support for PROXYv2 on a DoH or DNSCrypt listening interface.
Can list multiple, each on a new statement.
.TP
.B use\-systemd: \fI<yes or no>
Enable or disable systemd socket activation.
Default is no.
@ -1668,7 +1679,7 @@ This specifies the action data for \fIresponse-ip\fR with action being
to redirect as specified by "\fIresource record string\fR". "Resource
record string" is similar to that of \fIaccess-control-tag-action\fR,
but it must be of either AAAA, A or CNAME types.
If the IP-netblock is an IPv6/IPV4 prefix, the record
If the IP-netblock is an IPv6/IPv4 prefix, the record
must be AAAA/A respectively, unless it is a CNAME (which can be used
for both versions of IP netblocks). If it is CNAME there must not be
more than one \fIresponse-ip-data\fR for the same IP-netblock.

View File

@ -765,7 +765,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
}
else if(qstate->mesh_info->reply_list) {
subnet_option_from_ss(
&qstate->mesh_info->reply_list->query_reply.addr,
&qstate->mesh_info->reply_list->query_reply.client_addr,
&sq->ecs_client_in, qstate->env->cfg);
}

View File

@ -113,7 +113,11 @@ response_type_from_server(int rdset,
if(!msg || !request)
return RESPONSE_TYPE_THROWAWAY;
/* If the TC flag is set, the response is incomplete. Too large to
* fit even in TCP or so. Discard it, it cannot be retrieved here. */
if((msg->rep->flags & BIT_TC))
return RESPONSE_TYPE_THROWAWAY;
/* If the message is NXDOMAIN, then it answers the question. */
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
/* make sure its not recursive when we don't want it to */

View File

@ -255,9 +255,9 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
log_err("out of memory adding missing");
}
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
dpns->resolved = 1; /* mark as failed */
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* mark as failed */
target_count_increase_nx(super_iq, 1);
}
}
@ -596,15 +596,17 @@ errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
{
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
return;
if((qstate->reply && qstate->reply->addrlen != 0) ||
(iq->fail_reply && iq->fail_reply->addrlen != 0)) {
if((qstate->reply && qstate->reply->remote_addrlen != 0) ||
(iq->fail_reply && iq->fail_reply->remote_addrlen != 0)) {
char from[256], frm[512];
if(qstate->reply && qstate->reply->addrlen != 0)
addr_to_str(&qstate->reply->addr, qstate->reply->addrlen,
from, sizeof(from));
if(qstate->reply && qstate->reply->remote_addrlen != 0)
addr_to_str(&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, from,
sizeof(from));
else
addr_to_str(&iq->fail_reply->addr, iq->fail_reply->addrlen,
from, sizeof(from));
addr_to_str(&iq->fail_reply->remote_addr,
iq->fail_reply->remote_addrlen, from,
sizeof(from));
snprintf(frm, sizeof(frm), "from %s", from);
errinf(qstate, frm);
}
@ -2262,6 +2264,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
size_t qout_orig_len = 0;
int sq_check_ratelimit = 1;
int sq_was_ratelimited = 0;
int can_do_promisc = 0;
/* NOTE: a request will encounter this state for each target it
* needs to send a query to. That is, at least one per referral,
@ -2273,7 +2276,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->num_current_queries, iq->sent_count);
/* Make sure that we haven't run away */
/* FIXME: is this check even necessary? */
if(iq->referral_count > MAX_REFERRAL_COUNT) {
verbose(VERB_QUERY, "request has exceeded the maximum "
"number of referrrals with %d", iq->referral_count);
@ -2589,12 +2591,12 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
if(iq->depth < ie->max_dependency_depth
&& iq->num_target_queries == 0
&& (!iq->target_count || iq->target_count[TARGET_COUNT_NX]==0)
&& iq->sent_count < TARGET_FETCH_STOP
/* if the mesh query list is full, then do not waste cpu
* and sockets to fetch promiscuous targets. They can be
* looked up when needed. */
&& !mesh_jostle_exceeded(qstate->env->mesh)
) {
&& iq->sent_count < TARGET_FETCH_STOP) {
can_do_promisc = 1;
}
/* if the mesh query list is full, then do not waste cpu and sockets to
* fetch promiscuous targets. They can be looked up when needed. */
if(can_do_promisc && !mesh_jostle_exceeded(qstate->env->mesh)) {
tf_policy = ie->target_fetch_policy[iq->depth];
}
@ -2766,6 +2768,37 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
/* We have a target. We could have created promiscuous target
* queries but we are currently under pressure (mesh_jostle_exceeded).
* If we are configured to allow promiscuous target queries and haven't
* gone out to the network for a target query for this delegation, then
* it is possible to slip in a promiscuous one with a 1/10 chance. */
if(can_do_promisc && tf_policy == 0 && iq->depth == 0
&& iq->depth < ie->max_dependency_depth
&& ie->target_fetch_policy[iq->depth] != 0
&& iq->dp_target_count == 0
&& !ub_random_max(qstate->env->rnd, 10)) {
int extra = 0;
verbose(VERB_ALGO, "available target exists in cache but "
"attempt to get extra 1 target");
(void)query_for_targets(qstate, iq, ie, id, 1, &extra);
/* errors ignored, these targets are not strictly necessary for
* this result, we do not have to reply with SERVFAIL */
if(extra > 0) {
iq->num_target_queries += extra;
target_count_increase(iq, extra);
check_waiting_queries(iq, qstate, id);
/* undo qname minimise step because we'll get back here
* to do it again */
if(qout_orig && iq->minimise_count > 0) {
iq->minimise_count--;
iq->qinfo_out.qname = qout_orig;
iq->qinfo_out.qname_len = qout_orig_len;
}
return 0;
}
}
/* Do not check ratelimit for forwarding queries or if we already got a
* pass. */
sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok);
@ -2873,6 +2906,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
iq->response, &iq->qinfo_out, iq->dp);
iq->chase_to_rd = 0;
/* remove TC flag, if this is erroneously set by TCP upstream */
iq->response->rep->flags &= ~BIT_TC;
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
!iq->auth_zone_response) {
/* When forwarding (RD bit is set), we handle referrals
@ -2896,8 +2931,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* use dnssec-lame-bypass if it needs to query there.*/
if(qstate->reply) {
struct delegpt_addr* a = delegpt_find_addr(
iq->dp, &qstate->reply->addr,
qstate->reply->addrlen);
iq->dp, &qstate->reply->remote_addr,
qstate->reply->remote_addrlen);
if(a) a->dnsseclame = 1;
}
/* test the answer is from the zone we expected,
@ -2993,9 +3028,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
if(qstate->reply)
sock_list_insert(&qstate->reply_origin,
&qstate->reply->addr, qstate->reply->addrlen,
qstate->region);
sock_list_insert(&qstate->reply_origin,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, qstate->region);
if(iq->minimisation_state != DONOT_MINIMISE_STATE
&& !(iq->chase_flags & BIT_RD)) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
@ -3250,9 +3285,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
if(qstate->reply)
sock_list_insert(&qstate->reply_origin,
&qstate->reply->addr, qstate->reply->addrlen,
qstate->region);
sock_list_insert(&qstate->reply_origin,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, qstate->region);
verbose(VERB_ALGO, "cleared outbound list for query restart");
/* go to INIT_REQUEST_STATE for new qname. */
return next_state(iq, INIT_REQUEST_STATE);
@ -3266,9 +3301,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
} else if(qstate->reply) {
/* need addr for lameness cache, but we may have
* gotten this from cache, so test to be sure */
if(!infra_set_lame(qstate->env->infra_cache,
&qstate->reply->addr, qstate->reply->addrlen,
iq->dp->name, iq->dp->namelen,
if(!infra_set_lame(qstate->env->infra_cache,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen,
iq->dp->name, iq->dp->namelen,
*qstate->env->now, dnsseclame, 0,
iq->qchase.qtype))
log_err("mark host lame: out of memory");
@ -3285,8 +3321,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* gotten this from cache, so test to be sure */
verbose(VERB_DETAIL, "mark as REC_LAME");
if(!infra_set_lame(qstate->env->infra_cache,
&qstate->reply->addr, qstate->reply->addrlen,
iq->dp->name, iq->dp->namelen,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen,
iq->dp->name, iq->dp->namelen,
*qstate->env->now, 0, 1, iq->qchase.qtype))
log_err("mark host lame: out of memory");
}
@ -3527,12 +3564,13 @@ processTargetResponse(struct module_qstate* qstate, int id,
} else {
verbose(VERB_ALGO, "iterator TargetResponse failed");
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
dpns->resolved = 1; /* fail the target */
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
(dpns->got6 == 2 || !ie->supports_ipv6) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* fail the target */
/* do not count cached answers */
(qstate->reply_origin && qstate->reply_origin->len != 0)) {
target_count_increase_nx(foriq, 1);
if(qstate->reply_origin && qstate->reply_origin->len != 0) {
target_count_increase_nx(foriq, 1);
}
}
}
}
@ -4014,8 +4052,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
if(!iq->response)
goto handle_it;
log_query_info(VERB_DETAIL, "response for", &qstate->qinfo);
log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
&qstate->reply->addr, qstate->reply->addrlen);
log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
&qstate->reply->remote_addr, qstate->reply->remote_addrlen);
if(verbosity >= VERB_ALGO)
log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
iq->response->rep);

View File

@ -67,7 +67,8 @@ struct rbtree_type;
#define MAX_RESTART_COUNT 11
/** max number of referrals. Makes sure resolver does not run away */
#define MAX_REFERRAL_COUNT 130
/** max number of queries-sent-out. Make sure large NS set does not loop */
/** max number of queries-sent-out. Make sure large NS set does not loop.
* Resets on query restarts (e.g., CNAMES) and referrals. */
#define MAX_SENT_COUNT 32
/** max number of queries for which to perform dnsseclameness detection,
* (rrsigs missing detection) after that, just pick up that response */
@ -324,7 +325,7 @@ struct iter_qstate {
/** the number of times this query has been restarted. */
int query_restart_count;
/** the number of times this query as followed a referral. */
/** the number of times this query has followed a referral. */
int referral_count;
/** number of queries fired off */

View File

@ -609,9 +609,9 @@ struct mesh_reply {
struct comm_reply query_reply;
};
%rename(_addr) comm_reply::addr;
%rename(_addr) comm_reply::client_addr;
struct comm_reply {
struct sockaddr_storage addr;
struct sockaddr_storage client_addr;
};
%extend comm_reply {

View File

@ -172,14 +172,14 @@ int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
}
/* Convert reply->addr to string */
/* Convert reply->client_addr to string */
void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
{
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr;
int af = (int)((struct sockaddr_in*) &(reply->client_addr))->sin_family;
void* sinaddr = &((struct sockaddr_in*) &(reply->client_addr))->sin_addr;
if(af == AF_INET6)
sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr;
sinaddr = &((struct sockaddr_in6*)&(reply->client_addr))->sin6_addr;
dest[0] = 0;
if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
return;

View File

@ -1290,7 +1290,7 @@ respip_set_is_empty(const struct respip_set* set)
void
respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
struct comm_reply* repinfo)
struct sockaddr_storage* addr, socklen_t addrlen)
{
char srcip[128], respip[128], txt[512];
unsigned port;
@ -1300,10 +1300,10 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
if(local_alias)
qname = local_alias->rrset->rk.dname;
port = (unsigned)((repinfo->addr.ss_family == AF_INET) ?
ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port) :
ntohs(((struct sockaddr_in6*)&repinfo->addr)->sin6_port));
addr_to_str(&repinfo->addr, repinfo->addrlen, srcip, sizeof(srcip));
port = (unsigned)((addr->ss_family == AF_INET) ?
ntohs(((struct sockaddr_in*)addr)->sin_port) :
ntohs(((struct sockaddr_in6*)addr)->sin6_port));
addr_to_str(addr, addrlen, srcip, sizeof(srcip));
addr_to_str(&respip_addr->addr, respip_addr->addrlen,
respip, sizeof(respip));
if(respip_actinfo->rpz_log) {

View File

@ -251,11 +251,13 @@ int respip_set_is_empty(const struct respip_set* set);
* @param local_alias: set to a local alias if the query matches an alias in
* a local zone. In this case its owner name will be considered the actual
* query name.
* @param repinfo: reply info containing the client's source address and port.
* @param addr: the client's source address and port.
* @param addrlen: the client's source address length.
*/
void respip_inform_print(struct respip_action_info* respip_actinfo,
uint8_t* qname, uint16_t qtype, uint16_t qclass,
struct local_rrset* local_alias, struct comm_reply* repinfo);
struct local_rrset* local_alias, struct sockaddr_storage* addr,
socklen_t addrlen);
/**
* Find resp_addr in tree, create and add to tree if it does not exist.

View File

@ -834,14 +834,13 @@ static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
/** find data item in array for ip addresses */
static struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
struct comm_reply* repinfo, int wr)
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
{
struct ip_rate_key key;
hashvalue_type h = hash_addr(&(repinfo->addr),
repinfo->addrlen, 0);
hashvalue_type h = hash_addr(addr, addrlen, 0);
memset(&key, 0, sizeof(key));
key.addr = repinfo->addr;
key.addrlen = repinfo->addrlen;
key.addr = *addr;
key.addrlen = addrlen;
key.entry.hash = h;
return slabhash_lookup(infra->client_ip_rates, h, &key, wr);
}
@ -876,10 +875,9 @@ static void infra_create_ratedata(struct infra_cache* infra,
/** create rate data item for ip address */
static void infra_ip_create_ratedata(struct infra_cache* infra,
struct comm_reply* repinfo, time_t timenow)
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow)
{
hashvalue_type h = hash_addr(&(repinfo->addr),
repinfo->addrlen, 0);
hashvalue_type h = hash_addr(addr, addrlen, 0);
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d));
if(!k || !d) {
@ -887,8 +885,8 @@ static void infra_ip_create_ratedata(struct infra_cache* infra,
free(d);
return; /* alloc failure */
}
k->addr = repinfo->addr;
k->addrlen = repinfo->addrlen;
k->addr = *addr;
k->addrlen = addrlen;
lock_rw_init(&k->entry.lock);
k->entry.hash = h;
k->entry.key = k;
@ -985,8 +983,8 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
sldns_wire2str_class_buf(qinfo->qclass, cs, sizeof(cs));
ip[0]=0;
if(replylist) {
addr_to_str((struct sockaddr_storage *)&replylist->addr,
replylist->addrlen, ip, sizeof(ip));
addr_to_str((struct sockaddr_storage *)&replylist->remote_addr,
replylist->remote_addrlen, ip, sizeof(ip));
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s from %s", buf, lim, qnm, cs, ts, ip);
} else {
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s", buf, lim, qnm, cs, ts);
@ -1054,8 +1052,8 @@ infra_get_mem(struct infra_cache* infra)
}
int infra_ip_ratelimit_inc(struct infra_cache* infra,
struct comm_reply* repinfo, time_t timenow, int backoff,
struct sldns_buffer* buffer)
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
int backoff, struct sldns_buffer* buffer)
{
int max;
struct lruhash_entry* entry;
@ -1065,7 +1063,7 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
return 1;
}
/* find or insert ratedata */
entry = infra_find_ip_ratedata(infra, repinfo, 1);
entry = infra_find_ip_ratedata(infra, addr, addrlen, 1);
if(entry) {
int premax = infra_rate_max(entry->data, timenow, backoff);
int* cur = infra_rate_give_second(entry->data, timenow);
@ -1075,8 +1073,7 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
if(premax <= infra_ip_ratelimit && max > infra_ip_ratelimit) {
char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12];
addr_to_str((struct sockaddr_storage *)&repinfo->addr,
repinfo->addrlen, client_ip, sizeof(client_ip));
addr_to_str(addr, addrlen, client_ip, sizeof(client_ip));
qnm[0]=0;
if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE &&
LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) {
@ -1101,6 +1098,6 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
}
/* create */
infra_ip_create_ratedata(infra, repinfo, timenow);
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
return 1;
}

View File

@ -416,15 +416,16 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
/** Update query ratelimit hash and decide
* whether or not a query should be dropped.
* @param infra: infra cache
* @param repinfo: information about client
* @param addr: client address
* @param addrlen: client address length
* @param timenow: what time it is now.
* @param backoff: if backoff is enabled.
* @param buffer: with query for logging.
* @return 1 if it could be incremented. 0 if the increment overshot the
* ratelimit and the query should be dropped. */
int infra_ip_ratelimit_inc(struct infra_cache* infra,
struct comm_reply* repinfo, time_t timenow, int backoff,
struct sldns_buffer* buffer);
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
int backoff, struct sldns_buffer* buffer);
/**
* Get memory used by the infra cache.

View File

@ -1093,11 +1093,13 @@ make_sock_port(int stype, const char* ifname, const char* port,
* @param list: list head. changed.
* @param s: fd.
* @param ftype: if fd is UDP.
* @param pp2_enabled: if PROXYv2 is enabled for this port.
* @param ub_sock: socket with address.
* @return false on failure. list in unchanged then.
*/
static int
port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unbound_socket* ub_sock)
port_insert(struct listen_port** list, int s, enum listen_type ftype,
int pp2_enabled, struct unbound_socket* ub_sock)
{
struct listen_port* item = (struct listen_port*)malloc(
sizeof(struct listen_port));
@ -1106,6 +1108,7 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unb
item->next = *list;
item->fd = s;
item->ftype = ftype;
item->pp2_enabled = pp2_enabled;
item->socket = ub_sock;
*list = item;
return 1;
@ -1201,6 +1204,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @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 proxy_protocol_port: list of PROXYv2 port numbers.
* @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.
@ -1217,25 +1221,30 @@ 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 https_port,
struct config_strlist* proxy_protocol_port,
int* reuseport, int transparent, int tcp_mss, int freebind,
int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
{
int s, noip6=0;
int is_https = if_is_https(ifname, port, https_port);
int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port);
int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port);
int nodelay = is_https && http2_nodelay;
struct unbound_socket* ub_sock;
#ifdef USE_DNSCRYPT
int is_dnscrypt = ((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
(!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
#else
int is_dnscrypt = 0;
(void)dnscrypt_port;
#endif
if(!do_udp && !do_tcp)
return 0;
if(is_pp2) {
if(is_dnscrypt) {
fatal_exit("PROXYv2 and DNSCrypt combination not "
"supported!");
} else if(is_https) {
fatal_exit("PROXYv2 and DoH combination not "
"supported!");
}
}
if(do_auto) {
ub_sock = calloc(1, sizeof(struct unbound_socket));
if(!ub_sock)
@ -1260,7 +1269,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
if(!port_insert(list, s, is_dnscrypt
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
ub_sock)) {
is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
@ -1283,7 +1292,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
return 0;
}
if(!port_insert(list, s, is_dnscrypt
?listen_type_udp_dnscrypt:listen_type_udp, ub_sock)) {
?listen_type_udp_dnscrypt:listen_type_udp,
is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
@ -1318,7 +1328,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, port_type, ub_sock)) {
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
@ -1407,14 +1417,16 @@ listen_create(struct comm_base* base, struct listen_port* ports,
if(ports->ftype == listen_type_udp ||
ports->ftype == listen_type_udp_dnscrypt) {
cp = comm_point_create_udp(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket);
front->udp_buff, ports->pp2_enabled, cb,
cb_arg, ports->socket);
} else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) {
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
harden_large_queries, 0, NULL,
tcp_conn_limit, bufsize, front->udp_buff,
ports->ftype, cb, cb_arg, ports->socket);
ports->ftype, ports->pp2_enabled, cb, cb_arg,
ports->socket);
} else if(ports->ftype == listen_type_ssl ||
ports->ftype == listen_type_http) {
cp = comm_point_create_tcp(base, ports->fd,
@ -1422,7 +1434,8 @@ listen_create(struct comm_base* base, struct listen_port* ports,
harden_large_queries,
http_max_streams, http_endpoint,
tcp_conn_limit, bufsize, front->udp_buff,
ports->ftype, cb, cb_arg, ports->socket);
ports->ftype, ports->pp2_enabled, cb, cb_arg,
ports->socket);
if(ports->ftype == listen_type_http) {
if(!sslctx && !http_notls) {
log_warn("HTTPS port configured, but "
@ -1448,7 +1461,8 @@ listen_create(struct comm_base* base, struct listen_port* ports,
} else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt) {
cp = comm_point_create_udp_ancil(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket);
front->udp_buff, ports->pp2_enabled, cb,
cb_arg, ports->socket);
}
if(!cp) {
log_err("can't create commpoint");
@ -1783,7 +1797,9 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port,
cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1798,7 +1814,9 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port,
cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1816,7 +1834,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1831,7 +1850,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1848,7 +1868,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
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->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1863,7 +1884,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
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->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {

View File

@ -128,7 +128,10 @@ struct listen_port {
int fd;
/** type of file descriptor, udp or tcp */
enum listen_type ftype;
/** fill in unbpound_socket structure for every opened socket at Unbound startup */
/** if the port should support PROXYv2 */
int pp2_enabled;
/** fill in unbound_socket structure for every opened socket at
* Unbound startup */
struct unbound_socket* socket;
};

View File

@ -1744,13 +1744,13 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
/** print log information for an inform zone query */
static void
lz_inform_print(struct local_zone* z, struct query_info* qinfo,
struct comm_reply* repinfo)
struct sockaddr_storage* addr, socklen_t addrlen)
{
char ip[128], txt[512];
char zname[LDNS_MAX_DOMAINLEN+1];
uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
uint16_t port = ntohs(((struct sockaddr_in*)addr)->sin_port);
dname_str(z->name, zname);
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
addr_to_str(addr, addrlen, ip, sizeof(ip));
snprintf(txt, sizeof(txt), "%s %s %s@%u", zname, local_zone_type2str(z->type), ip,
(unsigned)port);
log_nametypeclass(NO_VERBOSE, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
@ -1765,7 +1765,8 @@ lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
struct local_zone_override* lzo;
if(repinfo && override_tree) {
lzo = (struct local_zone_override*)addr_tree_lookup(
override_tree, &repinfo->addr, repinfo->addrlen);
override_tree, &repinfo->client_addr,
repinfo->client_addrlen);
if(lzo && lzo->type) {
verbose(VERB_ALGO, "local zone override to type %s",
local_zone_type2str(lzo->type));
@ -1888,7 +1889,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
lzt == local_zone_inform_deny ||
lzt == local_zone_inform_redirect)
&& repinfo)
lz_inform_print(z, qinfo, repinfo);
lz_inform_print(z, qinfo, &repinfo->client_addr,
repinfo->client_addrlen);
if(lzt != local_zone_always_refuse
&& lzt != local_zone_always_transparent

View File

@ -806,7 +806,7 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
/* Fake the ECS data from the client's IP */
struct ecs_data ecs;
memset(&ecs, 0, sizeof(ecs));
subnet_option_from_ss(&rep->addr, &ecs, mesh->env->cfg);
subnet_option_from_ss(&rep->client_addr, &ecs, mesh->env->cfg);
if(ecs.subnet_validdata == 0) {
log_err("prefetch_subnet subnet_option_from_ss: invalid data");
return;
@ -1488,8 +1488,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
}
/* Log reply sent */
if(m->s.env->cfg->log_replies) {
log_reply_info(NO_VERBOSE, &m->s.qinfo, &r->query_reply.addr,
r->query_reply.addrlen, duration, 0, r_buffer);
log_reply_info(NO_VERBOSE, &m->s.qinfo,
&r->query_reply.client_addr,
r->query_reply.client_addrlen, duration, 0, r_buffer);
}
}
@ -1530,7 +1531,8 @@ void mesh_query_done(struct mesh_state* mstate)
respip_inform_print(mstate->s.respip_action_info,
r->qname, mstate->s.qinfo.qtype,
mstate->s.qinfo.qclass, r->local_alias,
&r->query_reply);
&r->query_reply.client_addr,
r->query_reply.client_addrlen);
if(mstate->s.env->cfg->stat_extended &&
mstate->s.respip_action_info->rpz_used) {
if(mstate->s.respip_action_info->rpz_disabled)
@ -2180,7 +2182,8 @@ mesh_serve_expired_callback(void* arg)
if(actinfo.addrinfo) {
respip_inform_print(&actinfo, r->qname,
qstate->qinfo.qtype, qstate->qinfo.qclass,
r->local_alias, &r->query_reply);
r->local_alias, &r->query_reply.client_addr,
r->query_reply.client_addrlen);
if(qstate->env->cfg->stat_extended && actinfo.rpz_used) {
if(actinfo.rpz_disabled)

View File

@ -86,10 +86,6 @@ static void serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff)
static int randomize_and_send_udp(struct pending* pend, sldns_buffer* packet,
int timeout);
/** remove waiting tcp from the outnet waiting list */
static void waiting_list_remove(struct outside_network* outnet,
struct waiting_tcp* w);
/** select a DNS ID for a TCP stream */
static uint16_t tcp_select_id(struct outside_network* outnet,
struct reuse_tcp* reuse);
@ -372,7 +368,8 @@ log_reuse_tcp(enum verbosity_value v, const char* msg, struct reuse_tcp* reuse)
}
/** pop the first element from the writewait list */
static struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse)
struct waiting_tcp*
reuse_write_wait_pop(struct reuse_tcp* reuse)
{
struct waiting_tcp* w = reuse->write_wait_first;
if(!w)
@ -390,8 +387,8 @@ static struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse)
}
/** remove the element from the writewait list */
static void reuse_write_wait_remove(struct reuse_tcp* reuse,
struct waiting_tcp* w)
void
reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w)
{
log_assert(w);
log_assert(w->write_wait_queued);
@ -415,8 +412,8 @@ static void reuse_write_wait_remove(struct reuse_tcp* reuse,
}
/** push the element after the last on the writewait list */
static void reuse_write_wait_push_back(struct reuse_tcp* reuse,
struct waiting_tcp* w)
void
reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w)
{
if(!w) return;
log_assert(!w->write_wait_queued);
@ -427,7 +424,9 @@ static void reuse_write_wait_push_back(struct reuse_tcp* reuse,
w->write_wait_prev = reuse->write_wait_last;
} else {
reuse->write_wait_first = w;
w->write_wait_prev = NULL;
}
w->write_wait_next = NULL;
reuse->write_wait_last = w;
w->write_wait_queued = 1;
}
@ -721,12 +720,12 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
pend->next_free = NULL;
pend->query = w;
pend->reuse.outnet = w->outnet;
pend->c->repinfo.addrlen = w->addrlen;
pend->c->repinfo.remote_addrlen = w->addrlen;
pend->c->tcp_more_read_again = &pend->reuse.cp_more_read_again;
pend->c->tcp_more_write_again = &pend->reuse.cp_more_write_again;
pend->reuse.cp_more_read_again = 0;
pend->reuse.cp_more_write_again = 0;
memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen);
memcpy(&pend->c->repinfo.remote_addr, &w->addr, w->addrlen);
pend->reuse.pending = pend;
/* Remove from tree in case the is_ssl will be different and causes the
@ -810,20 +809,50 @@ reuse_tcp_lru_snip(struct outside_network* outnet)
return reuse;
}
/** call callback on waiting_tcp, if not NULL */
static void
waiting_tcp_callback(struct waiting_tcp* w, struct comm_point* c, int error,
struct comm_reply* reply_info)
/** remove waiting tcp from the outnet waiting list */
void
outnet_waiting_tcp_list_remove(struct outside_network* outnet, struct waiting_tcp* w)
{
if(w && w->cb) {
fptr_ok(fptr_whitelist_pending_tcp(w->cb));
(void)(*w->cb)(c, w->cb_arg, error, reply_info);
struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL;
w->on_tcp_waiting_list = 0;
while(p) {
if(p == w) {
/* remove w */
if(prev)
prev->next_waiting = w->next_waiting;
else outnet->tcp_wait_first = w->next_waiting;
if(outnet->tcp_wait_last == w)
outnet->tcp_wait_last = prev;
w->next_waiting = NULL;
return;
}
prev = p;
p = p->next_waiting;
}
/* outnet_waiting_tcp_list_remove is currently called only with items
* that are already in the waiting list. */
log_assert(0);
}
/** pop the first waiting tcp from the outnet waiting list */
struct waiting_tcp*
outnet_waiting_tcp_list_pop(struct outside_network* outnet)
{
struct waiting_tcp* w = outnet->tcp_wait_first;
if(!outnet->tcp_wait_first) return NULL;
log_assert(w->on_tcp_waiting_list);
outnet->tcp_wait_first = w->next_waiting;
if(outnet->tcp_wait_last == w)
outnet->tcp_wait_last = NULL;
w->on_tcp_waiting_list = 0;
w->next_waiting = NULL;
return w;
}
/** add waiting_tcp element to the outnet tcp waiting list */
static void
outnet_add_tcp_waiting(struct outside_network* outnet, struct waiting_tcp* w)
void
outnet_waiting_tcp_list_add(struct outside_network* outnet,
struct waiting_tcp* w, int set_timer)
{
struct timeval tv;
log_assert(!w->on_tcp_waiting_list);
@ -835,16 +864,18 @@ outnet_add_tcp_waiting(struct outside_network* outnet, struct waiting_tcp* w)
else outnet->tcp_wait_first = w;
outnet->tcp_wait_last = w;
w->on_tcp_waiting_list = 1;
if(set_timer) {
#ifndef S_SPLINT_S
tv.tv_sec = w->timeout/1000;
tv.tv_usec = (w->timeout%1000)*1000;
tv.tv_sec = w->timeout/1000;
tv.tv_usec = (w->timeout%1000)*1000;
#endif
comm_timer_set(w->timer, &tv);
comm_timer_set(w->timer, &tv);
}
}
/** add waiting_tcp element as first to the outnet tcp waiting list */
static void
outnet_add_tcp_waiting_first(struct outside_network* outnet,
void
outnet_waiting_tcp_list_add_first(struct outside_network* outnet,
struct waiting_tcp* w, int reset_timer)
{
struct timeval tv;
@ -869,6 +900,17 @@ outnet_add_tcp_waiting_first(struct outside_network* outnet,
(outnet->tcp_reuse_first && outnet->tcp_reuse_last));
}
/** call callback on waiting_tcp, if not NULL */
static void
waiting_tcp_callback(struct waiting_tcp* w, struct comm_point* c, int error,
struct comm_reply* reply_info)
{
if(w && w->cb) {
fptr_ok(fptr_whitelist_pending_tcp(w->cb));
(void)(*w->cb)(c, w->cb_arg, error, reply_info);
}
}
/** see if buffers can be used to service TCP queries */
static void
use_free_buffer(struct outside_network* outnet)
@ -879,15 +921,10 @@ use_free_buffer(struct outside_network* outnet)
struct pending_tcp* pend_tcp = NULL;
#endif
struct reuse_tcp* reuse = NULL;
w = outnet->tcp_wait_first;
log_assert(w->on_tcp_waiting_list);
outnet->tcp_wait_first = w->next_waiting;
if(outnet->tcp_wait_last == w)
outnet->tcp_wait_last = NULL;
w = outnet_waiting_tcp_list_pop(outnet);
log_assert(
(!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) ||
(outnet->tcp_reuse_first && outnet->tcp_reuse_last));
w->on_tcp_waiting_list = 0;
reuse = reuse_tcp_find(outnet, &w->addr, w->addrlen,
w->ssl_upstream);
/* re-select an ID when moving to a new TCP buffer */
@ -934,7 +971,7 @@ use_free_buffer(struct outside_network* outnet)
#endif
} else {
/* no reuse and no free buffer, put back at the start */
outnet_add_tcp_waiting_first(outnet, w, 0);
outnet_waiting_tcp_list_add_first(outnet, w, 0);
break;
}
#ifdef USE_DNSTAP
@ -1008,7 +1045,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
* fail the query */
w->error_count ++;
reuse_tree_by_id_delete(&pend->reuse, w);
outnet_add_tcp_waiting(outnet, w);
outnet_waiting_tcp_list_add(outnet, w, 1);
}
while((w = reuse_write_wait_pop(&pend->reuse)) != NULL) {
if(verbosity >= VERB_CLIENT && w->pkt_len > 12+2+2 &&
@ -1019,7 +1056,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
verbose(VERB_CLIENT, "reuse_move_writewait_away item %s", buf);
}
reuse_tree_by_id_delete(&pend->reuse, w);
outnet_add_tcp_waiting(outnet, w);
outnet_waiting_tcp_list_add(outnet, w, 1);
}
}
@ -1417,11 +1454,11 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
/* setup lookup key */
key.id = (unsigned)LDNS_ID_WIRE(sldns_buffer_begin(c->buffer));
memcpy(&key.addr, &reply_info->addr, reply_info->addrlen);
key.addrlen = reply_info->addrlen;
memcpy(&key.addr, &reply_info->remote_addr, reply_info->remote_addrlen);
key.addrlen = reply_info->remote_addrlen;
verbose(VERB_ALGO, "Incoming reply id = %4.4x", key.id);
log_addr(VERB_ALGO, "Incoming reply addr =",
&reply_info->addr, reply_info->addrlen);
&reply_info->remote_addr, reply_info->remote_addrlen);
/* find it, see if this thing is a valid query response */
verbose(VERB_ALGO, "lookup size is %d entries", (int)outnet->pending->count);
@ -1690,7 +1727,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
return NULL;
}
pc->cp = comm_point_create_udp(outnet->base, -1,
outnet->udp_buff, outnet_udp_cb, outnet, NULL);
outnet->udp_buff, 0, outnet_udp_cb, outnet, NULL);
if(!pc->cp) {
log_err("malloc failed");
free(pc);
@ -2237,7 +2274,7 @@ outnet_tcptimer(void* arg)
verbose(VERB_CLIENT, "outnet_tcptimer");
if(w->on_tcp_waiting_list) {
/* it is on the waiting list */
waiting_list_remove(outnet, w);
outnet_waiting_tcp_list_remove(outnet, w);
waiting_tcp_callback(w, NULL, NETEVENT_TIMEOUT, NULL);
waiting_tcp_delete(w);
} else {
@ -2464,7 +2501,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
#ifdef USE_DNSTAP
w->sq = sq;
#endif
outnet_add_tcp_waiting(sq->outnet, w);
outnet_waiting_tcp_list_add(sq->outnet, w, 1);
}
return w;
}
@ -2612,30 +2649,6 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
return sq;
}
/** remove waiting tcp from the outnet waiting list */
static void
waiting_list_remove(struct outside_network* outnet, struct waiting_tcp* w)
{
struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL;
w->on_tcp_waiting_list = 0;
while(p) {
if(p == w) {
/* remove w */
if(prev)
prev->next_waiting = w->next_waiting;
else outnet->tcp_wait_first = w->next_waiting;
if(outnet->tcp_wait_last == w)
outnet->tcp_wait_last = prev;
return;
}
prev = p;
p = p->next_waiting;
}
/* waiting_list_remove is currently called only with items that are
* already in the waiting list. */
log_assert(0);
}
/** reuse tcp stream, remove serviced query from stream,
* return true if the stream is kept, false if it is to be closed */
static int
@ -2730,7 +2743,7 @@ serviced_delete(struct serviced_query* sq)
sq->pending = NULL;
} else {
verbose(VERB_CLIENT, "serviced_delete: tcpwait");
waiting_list_remove(sq->outnet, w);
outnet_waiting_tcp_list_remove(sq->outnet, w);
if(!w->in_cb_and_decommission)
waiting_tcp_delete(w);
}
@ -3103,8 +3116,8 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
rep = &r2;
r2.c = c;
}
memcpy(&rep->addr, &sq->addr, sq->addrlen);
rep->addrlen = sq->addrlen;
memcpy(&rep->remote_addr, &sq->addr, sq->addrlen);
rep->remote_addrlen = sq->addrlen;
serviced_callbacks(sq, error, c, rep);
return 0;
}
@ -3582,7 +3595,7 @@ outnet_comm_point_for_udp(struct outside_network* outnet,
if(fd == -1) {
return NULL;
}
cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff,
cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff, 0,
cb, cb_arg, NULL);
if(!cp) {
log_err("malloc failure");
@ -3670,8 +3683,8 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
close(fd);
return 0;
}
cp->repinfo.addrlen = to_addrlen;
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
cp->repinfo.remote_addrlen = to_addrlen;
memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
/* setup for SSL (if needed) */
if(ssl) {
@ -3746,8 +3759,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
close(fd);
return 0;
}
cp->repinfo.addrlen = to_addrlen;
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
cp->repinfo.remote_addrlen = to_addrlen;
memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
/* setup for SSL (if needed) */
if(ssl) {

View File

@ -718,6 +718,30 @@ struct reuse_tcp* reuse_tcp_lru_snip(struct outside_network* outnet);
/** delete readwait waiting_tcp elements, deletes the elements in the list */
void reuse_del_readwait(rbtree_type* tree_by_id);
/** remove waiting tcp from the outnet waiting list */
void outnet_waiting_tcp_list_remove(struct outside_network* outnet,
struct waiting_tcp* w);
/** pop the first waiting tcp from the outnet waiting list */
struct waiting_tcp* outnet_waiting_tcp_list_pop(struct outside_network* outnet);
/** add waiting_tcp element to the outnet tcp waiting list */
void outnet_waiting_tcp_list_add(struct outside_network* outnet,
struct waiting_tcp* w, int set_timer);
/** add waiting_tcp element as first to the outnet tcp waiting list */
void outnet_waiting_tcp_list_add_first(struct outside_network* outnet,
struct waiting_tcp* w, int reset_timer);
/** pop the first element from the writewait list */
struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse);
/** remove the element from the writewait list */
void reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w);
/** push the element after the last on the writewait list */
void reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w);
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,

View File

@ -1392,11 +1392,13 @@ log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
dnamestr[0]=0;
}
if(repinfo) {
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port);
} else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
addr_to_str(&ms->mesh_info->reply_list->query_reply.addr, ms->mesh_info->reply_list->query_reply.addrlen, ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.addr)->sin_port);
addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr,
ms->mesh_info->reply_list->query_reply.client_addrlen,
ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port);
} else {
ip[0]=0;
port = 0;
@ -1468,7 +1470,9 @@ rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qin
}
z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
qinfo->qclass, 0, 0, 0);
node = rpz_ipbased_trigger_lookup(r->client_set, &repinfo->addr, repinfo->addrlen, "clientip");
node = rpz_ipbased_trigger_lookup(r->client_set,
&repinfo->client_addr, repinfo->client_addrlen,
"clientip");
if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
if(r->log)
log_rpz_apply((node?"clientip":"qname"),
@ -2164,18 +2168,16 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
lock_rw_unlock(&az->rpz_lock);
if(raddr == NULL && z == NULL) { return NULL; }
else if(raddr != NULL) {
if(raddr == NULL && z == NULL)
return NULL;
if(raddr != NULL) {
if(z) {
lock_rw_unlock(&z->lock);
}
return rpz_apply_nsip_trigger(ms, r, raddr, a);
} else if(z != NULL) {
if(raddr) {
lock_rw_unlock(&raddr->lock);
}
return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
} else { return NULL; }
}
return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
}
struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,

View File

@ -338,6 +338,8 @@ interfacechecks(struct config_file* cfg)
int i, j, i2, j2;
char*** resif = NULL;
int* num_resif = NULL;
char portbuf[32];
snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
if(cfg->num_ifs != 0) {
resif = (char***)calloc(cfg->num_ifs, sizeof(char**));
@ -359,9 +361,21 @@ interfacechecks(struct config_file* cfg)
fatal_exit("could not resolve interface names, for %s",
cfg->ifs[i]);
}
/* check for port combinations that are not supported */
if(if_is_pp2(resif[i][0], portbuf, cfg->proxy_protocol_port)) {
if(if_is_dnscrypt(resif[i][0], portbuf,
cfg->dnscrypt_port)) {
fatal_exit("PROXYv2 and DNSCrypt combination not "
"supported!");
} else if(if_is_https(resif[i][0], portbuf,
cfg->https_port)) {
fatal_exit("PROXYv2 and DoH combination not "
"supported!");
}
}
/* search for duplicates in the returned addresses */
for(j=0; j<num_resif[i]; j++) {
if(!extstrtoaddr(resif[i][j], &a, &alen, UNBOUND_DNS_PORT)) {
if(!extstrtoaddr(resif[i][j], &a, &alen, cfg->port)) {
if(strcmp(cfg->ifs[i], resif[i][j]) != 0)
fatal_exit("cannot parse interface address '%s' from the interface specified as '%s'",
resif[i][j], cfg->ifs[i]);

View File

@ -16,7 +16,7 @@ NEED_WHOAMI='07-confroot.tdir'
NEED_IPV6='fwd_ancil.tdir fwd_tcp_tc6.tdir stub_udp6.tdir edns_cache.tdir'
NEED_NOMINGW='tcp_sigpipe.tdir 07-confroot.tdir 08-host-lib.tdir fwd_ancil.tdir'
NEED_DNSCRYPT_PROXY='dnscrypt_queries.tdir dnscrypt_queries_chacha.tdir'
NEED_UNSHARE='acl_interface.tdir'
NEED_UNSHARE='acl_interface.tdir proxy_protocol.tdir'
# test if dig and ldns-testns are available.
test_tool_avail "dig"

View File

@ -573,6 +573,7 @@ int main(int argc, char** argv)
#endif
checklock_start();
log_init(0, 0, 0);
log_ident_set("dohclient");
h2_session = http2_session_create();
if(!h2_session) fatal_exit("out of memory");

View File

@ -384,8 +384,8 @@ answer_callback_from_entry(struct replay_runtime* runtime,
fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len,
pend->tcp_pkt_counter);
repinfo.c = &c;
repinfo.addrlen = pend->addrlen;
memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
repinfo.remote_addrlen = pend->addrlen;
memcpy(&repinfo.remote_addr, &pend->addr, pend->addrlen);
if(!pend->serviced) {
if(entry && entry->reply_list->next &&
pend->tcp_pkt_counter < count_reply_packets(entry)) {
@ -415,7 +415,7 @@ answer_check_it(struct replay_runtime* runtime)
tr = transport_udp;
if((runtime->now->addrlen == 0 || sockaddr_cmp(
&runtime->now->addr, runtime->now->addrlen,
&ans->repinfo.addr, ans->repinfo.addrlen) == 0) &&
&ans->repinfo.remote_addr, ans->repinfo.remote_addrlen) == 0) &&
find_match(runtime->now->match, ans->pkt,
ans->pkt_len, tr)) {
log_info("testbound matched event entry from line %d",
@ -453,10 +453,12 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
if(!repinfo.c)
fatal_exit("out of memory in fake_front_query");
repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
repinfo.remote_addrlen = (socklen_t)sizeof(struct sockaddr_in);
if(todo->addrlen != 0) {
repinfo.addrlen = todo->addrlen;
memcpy(&repinfo.addr, &todo->addr, todo->addrlen);
repinfo.remote_addrlen = todo->addrlen;
memcpy(&repinfo.remote_addr, &todo->addr, todo->addrlen);
repinfo.client_addrlen = todo->addrlen;
memcpy(&repinfo.client_addr, &todo->addr, todo->addrlen);
}
repinfo.c->fd = -1;
repinfo.c->ev = (struct internal_event*)runtime;
@ -510,8 +512,8 @@ fake_pending_callback(struct replay_runtime* runtime,
p->pkt_len, p->tcp_pkt_counter);
}
repinfo.c = &c;
repinfo.addrlen = p->addrlen;
memcpy(&repinfo.addr, &p->addr, p->addrlen);
repinfo.remote_addrlen = p->addrlen;
memcpy(&repinfo.remote_addr, &p->addr, p->addrlen);
if(!p->serviced) {
if(todo->match && todo->match->reply_list->next && !error &&
p->tcp_pkt_counter < count_reply_packets(todo->match)) {
@ -1665,6 +1667,7 @@ int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype),
struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer),
int ATTR_UNUSED(pp2_enabled),
comm_point_callback_type* ATTR_UNUSED(callback),
void* ATTR_UNUSED(callback_arg),
struct unbound_socket* ATTR_UNUSED(socket))

View File

@ -8,6 +8,7 @@ fi
# This will keep the temporary directory around and return 1 when the test failed.
DEBUG=0
test -n "$DEBUG_TDIR" && DEBUG=1
quiet=0
if test "$1" = "-q"; then
@ -56,7 +57,7 @@ if test "$1" = "-f" && test "$2" = "report"; then
fi
elif test -f ".skip-$name"; then
echo ".. SKIPPED.. $timelen $name: $desc"
skip=`expr $pass + 1`
skip=`expr $skip + 1`
else
if test -f "result.$name"; then
echo "!! FAILED !! $timelen $name: $desc"
@ -92,7 +93,9 @@ if test "$1" = "report" || test "$2" = "report"; then
if test -f "result.$name"; then
echo "!! FAILED !! : $name"
else
echo ".. SKIPPED.. : $name"
if test $quiet = 0; then
echo ".. SKIPPED.. : $name"
fi
fi
fi
done
@ -211,7 +214,7 @@ if test $DEBUG -eq 0; then
rm -rf $dir
fi
else
if test $success == "no"; then
if test $success = "no"; then
exit 1
fi
exit 0

View File

@ -49,6 +49,7 @@
#include "util/locks.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/proxy_protocol.h"
#include "util/data/msgencode.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
@ -71,6 +72,7 @@ static void usage(char* argv[])
printf("usage: %s [options] name type class ...\n", argv[0]);
printf(" sends the name-type-class queries over TCP.\n");
printf("-f server what ipaddr@portnr to send the queries to\n");
printf("-p client what ipaddr@portnr to include in PROXYv2\n");
printf("-u use UDP. No retries are attempted.\n");
printf("-n do not wait for an answer.\n");
printf("-a print answers as they arrive.\n");
@ -82,18 +84,17 @@ static void usage(char* argv[])
/** open TCP socket to svr */
static int
open_svr(const char* svr, int udp)
open_svr(const char* svr, int udp, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
struct sockaddr_storage addr;
socklen_t addrlen;
int fd = -1;
/* svr can be ip@port */
memset(&addr, 0, sizeof(addr));
if(!extstrtoaddr(svr, &addr, &addrlen, UNBOUND_DNS_PORT)) {
memset(addr, 0, sizeof(*addr));
if(!extstrtoaddr(svr, addr, addrlen, UNBOUND_DNS_PORT)) {
printf("fatal: bad server specs '%s'\n", svr);
exit(1);
}
fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET,
fd = socket(addr_is_ip6(addr, *addrlen)?PF_INET6:PF_INET,
udp?SOCK_DGRAM:SOCK_STREAM, 0);
if(fd == -1) {
#ifndef USE_WINSOCK
@ -103,7 +104,7 @@ open_svr(const char* svr, int udp)
#endif
exit(1);
}
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
if(connect(fd, (struct sockaddr*)addr, *addrlen) < 0) {
#ifndef USE_WINSOCK
perror("connect() error");
#else
@ -116,11 +117,12 @@ open_svr(const char* svr, int udp)
/** write a query over the TCP fd */
static void
write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
sldns_buffer* proxy_buf, int pp2_parsed,
const char* strname, const char* strtype, const char* strclass)
{
struct query_info qinfo;
uint16_t len;
size_t proxy_buf_limit = sldns_buffer_limit(proxy_buf);
/* qname */
qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len);
if(!qinfo.qname) {
@ -152,9 +154,27 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
attach_edns_record(buf, &edns);
}
/* we need to send the PROXYv2 information in every UDP message */
if(udp && pp2_parsed) {
/* append the proxy_buf with the buf's content
* and use that for sending */
if(sldns_buffer_capacity(proxy_buf) <
sldns_buffer_limit(proxy_buf) +
sldns_buffer_limit(buf)) {
printf("buffer too small for packet + proxy");
exit(1);
}
sldns_buffer_clear(proxy_buf);
sldns_buffer_skip(proxy_buf, proxy_buf_limit);
sldns_buffer_write(proxy_buf, sldns_buffer_begin(buf),
sldns_buffer_limit(buf));
sldns_buffer_flip(proxy_buf);
buf = proxy_buf;
}
/* send it */
if(!udp) {
len = (uint16_t)sldns_buffer_limit(buf);
uint16_t len = (uint16_t)sldns_buffer_limit(buf);
len = htons(len);
if(ssl) {
if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
@ -167,7 +187,7 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
#ifndef USE_WINSOCK
perror("send() len failed");
#else
printf("send len: %s\n",
printf("send len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -182,17 +202,20 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
}
} else {
if(send(fd, (void*)sldns_buffer_begin(buf),
sldns_buffer_limit(buf), 0) <
sldns_buffer_limit(buf), 0) <
(ssize_t)sldns_buffer_limit(buf)) {
#ifndef USE_WINSOCK
perror("send() data failed");
#else
printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
printf("send data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
}
/* reset the proxy_buf for next packet */
sldns_buffer_set_limit(proxy_buf, proxy_buf_limit);
free(qinfo.qname);
}
@ -224,7 +247,7 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
#ifndef USE_WINSOCK
perror("read() len failed");
#else
printf("read len: %s\n",
printf("read len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -243,12 +266,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
if(r != (int)len)
fatal_exit("ssl_read %d of %d", r, len);
} else {
if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
(ssize_t)len) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
printf("read data: %s\n",
printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -257,12 +280,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
} else {
ssize_t l;
sldns_buffer_clear(buf);
if((l=recv(fd, (void*)sldns_buffer_begin(buf),
if((l=recv(fd, (void*)sldns_buffer_begin(buf),
sldns_buffer_capacity(buf), 0)) < 0) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
printf("read data: %s\n",
printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -324,17 +347,40 @@ static int get_random(void)
return (int)arc4random();
}
/* parse the pp2_client and populate the proxy_buffer
* It doesn't populate the destination parts. */
static int parse_pp2_client(const char* pp2_client, int udp,
sldns_buffer* proxy_buf)
{
struct sockaddr_storage pp2_addr;
socklen_t pp2_addrlen = 0;
memset(&pp2_addr, 0, sizeof(pp2_addr));
if(*pp2_client == 0) return 0;
if(!extstrtoaddr(pp2_client, &pp2_addr, &pp2_addrlen, UNBOUND_DNS_PORT)) {
printf("fatal: bad proxy client specs '%s'\n", pp2_client);
exit(1);
}
sldns_buffer_clear(proxy_buf);
pp2_write_to_buf(proxy_buf, &pp2_addr, !udp);
sldns_buffer_flip(proxy_buf);
return 1;
}
/** send the TCP queries and print answers */
static void
send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
int delay, int num, char** qs)
send_em(const char* svr, const char* pp2_client, int udp, int usessl,
int noanswer, int onarrival, int delay, int num, char** qs)
{
sldns_buffer* buf = sldns_buffer_new(65553);
int fd = open_svr(svr, udp);
int i, wait_results = 0;
sldns_buffer* proxy_buf = sldns_buffer_new(65553);
struct sockaddr_storage svr_addr;
socklen_t svr_addrlen;
int fd = open_svr(svr, udp, &svr_addr, &svr_addrlen);
int i, wait_results = 0, pp2_parsed;
SSL_CTX* ctx = NULL;
SSL* ssl = NULL;
if(!buf) fatal_exit("out of memory");
pp2_parsed = parse_pp2_client(pp2_client, udp, proxy_buf);
if(usessl) {
ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
if(!ctx) fatal_exit("cannot create ssl ctx");
@ -361,6 +407,28 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
}
}
/* Send the PROXYv2 information once per stream */
if(!udp && pp2_parsed) {
if(ssl) {
if(SSL_write(ssl, (void*)sldns_buffer_begin(proxy_buf),
(int)sldns_buffer_limit(proxy_buf)) <= 0) {
log_crypto_err("cannot SSL_write");
exit(1);
}
} else {
if(send(fd, (void*)sldns_buffer_begin(proxy_buf),
sldns_buffer_limit(proxy_buf), 0) <
(ssize_t)sldns_buffer_limit(proxy_buf)) {
#ifndef USE_WINSOCK
perror("send() data failed");
#else
printf("send data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
}
}
for(i=0; i<num; i+=3) {
if (delay != 0) {
#ifdef HAVE_SLEEP
@ -370,8 +438,9 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
#endif
}
printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i],
qs[i+1], qs[i+2]);
write_q(fd, udp, ssl, buf, (uint16_t)get_random(), proxy_buf,
pp2_parsed,
qs[i], qs[i+1], qs[i+2]);
/* print at least one result */
if(onarrival) {
wait_results += 1; /* one more answer to fetch */
@ -390,6 +459,7 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
sock_close(fd);
sldns_buffer_free(buf);
sldns_buffer_free(proxy_buf);
printf("orderly exit\n");
}
@ -418,10 +488,11 @@ extern int optind;
extern char* optarg;
/** main program for streamtcp */
int main(int argc, char** argv)
int main(int argc, char** argv)
{
int c;
const char* svr = "127.0.0.1";
const char* pp2_client = "";
int udp = 0;
int noanswer = 0;
int onarrival = 0;
@ -451,11 +522,14 @@ int main(int argc, char** argv)
if(argc == 1) {
usage(argv);
}
while( (c=getopt(argc, argv, "af:hnsud:")) != -1) {
while( (c=getopt(argc, argv, "af:p:hnsud:")) != -1) {
switch(c) {
case 'f':
svr = optarg;
break;
case 'p':
pp2_client = optarg;
break;
case 'a':
onarrival = 1;
break;
@ -508,7 +582,7 @@ int main(int argc, char** argv)
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
}
send_em(svr, udp, usessl, noanswer, onarrival, delay, argc, argv);
send_em(svr, pp2_client, udp, usessl, noanswer, onarrival, delay, argc, argv);
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();

View File

@ -44,6 +44,8 @@
#include "util/random.h"
#include "services/outside_network.h"
#define MAX_TCP_WAITING_NODES 5
/** add number of new IDs to the reuse tree, randomly chosen */
static void tcpid_addmore(struct reuse_tcp* reuse,
struct outside_network* outnet, unsigned int addnum)
@ -228,9 +230,260 @@ static void tcp_reuse_tree_list_test(void)
free(outnet.tcp_conns);
}
static void check_waiting_tcp_list(struct outside_network* outnet,
struct waiting_tcp* first, struct waiting_tcp* last, size_t total)
{
size_t i, j;
struct waiting_tcp* w = outnet->tcp_wait_first;
struct waiting_tcp* n = NULL;
if(first) unit_assert(outnet->tcp_wait_first == first);
if(last) unit_assert(outnet->tcp_wait_last == last && !last->next_waiting);
for(i=0; w; i++) {
unit_assert(i<total); /* otherwise we are looping */
unit_assert(w->on_tcp_waiting_list);
n = w->next_waiting;
for(j=0; n; j++) {
unit_assert(j<total-i-1); /* otherwise we are looping */
unit_assert(n != w);
n = n->next_waiting;
}
w = w->next_waiting;
}
}
/** clear the tcp waiting list */
static void waiting_tcp_list_clear(struct outside_network* outnet)
{
struct waiting_tcp* w = outnet->tcp_wait_first, *n = NULL;
if(!w) return;
unit_assert(outnet->tcp_wait_first);
unit_assert(outnet->tcp_wait_last);
while(w) {
n = w->next_waiting;
w->on_tcp_waiting_list = 0;
w->next_waiting = (struct waiting_tcp*)1; /* In purpose faux value */
w = n;
}
outnet->tcp_wait_first = NULL;
outnet->tcp_wait_last = NULL;
}
/** check removal of the waiting_tcp element on the given position of total
* elements */
static void check_waiting_tcp_removal(int is_pop,
struct outside_network* outnet, struct waiting_tcp* store,
size_t position, size_t total)
{
size_t i;
struct waiting_tcp* w;
waiting_tcp_list_clear(outnet);
for(i=0; i<total; i++) {
outnet_waiting_tcp_list_add(outnet, &store[i], 0);
}
check_waiting_tcp_list(outnet, &store[0], &store[total-1], total);
if(is_pop) {
w = outnet_waiting_tcp_list_pop(outnet);
unit_assert(w); /* please clang-analyser */
} else {
w = outnet->tcp_wait_first;
for(i=0; i<position; i++) {
unit_assert(w); /* please clang-analyser */
w = w->next_waiting;
}
unit_assert(w); /* please clang-analyser */
outnet_waiting_tcp_list_remove(outnet, w);
}
unit_assert(!(w->on_tcp_waiting_list || w->next_waiting));
if(position == 0 && total == 1) {
/* the list should be empty */
check_waiting_tcp_list(outnet, NULL, NULL, total-1);
} else if(position == 0) {
/* first element should be gone */
check_waiting_tcp_list(outnet, &store[1], &store[total-1], total-1);
} else if(position == total - 1) {
/* last element should be gone */
check_waiting_tcp_list(outnet, &store[0], &store[total-2], total-1);
} else {
/* an element should be gone */
check_waiting_tcp_list(outnet, &store[0], &store[total-1], total-1);
}
}
static void waiting_tcp_list_test(void)
{
size_t i = 0;
struct outside_network outnet;
struct waiting_tcp* w, *t = NULL;
struct waiting_tcp store[MAX_TCP_WAITING_NODES];
memset(&outnet, 0, sizeof(outnet));
memset(&store, 0, sizeof(store));
/* Check add first on empty list */
unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_add_first");
t = &store[i];
outnet_waiting_tcp_list_add_first(&outnet, t, 0);
check_waiting_tcp_list(&outnet, t, t, 1);
/* Check add */
unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_add");
for(i=1; i<MAX_TCP_WAITING_NODES-1; i++) {
w = &store[i];
outnet_waiting_tcp_list_add(&outnet, w, 0);
}
check_waiting_tcp_list(&outnet, t, w, MAX_TCP_WAITING_NODES-1);
/* Check add first on populated list */
unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_add_first");
w = &store[i];
t = outnet.tcp_wait_last;
outnet_waiting_tcp_list_add_first(&outnet, w, 0);
check_waiting_tcp_list(&outnet, w, t, MAX_TCP_WAITING_NODES);
/* Check removal */
unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_remove");
check_waiting_tcp_removal(0, &outnet, store, 2, 5);
check_waiting_tcp_removal(0, &outnet, store, 1, 3);
check_waiting_tcp_removal(0, &outnet, store, 0, 2);
check_waiting_tcp_removal(0, &outnet, store, 1, 2);
check_waiting_tcp_removal(0, &outnet, store, 0, 1);
/* Check pop */
unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_pop");
check_waiting_tcp_removal(1, &outnet, store, 0, 3);
check_waiting_tcp_removal(1, &outnet, store, 0, 2);
check_waiting_tcp_removal(1, &outnet, store, 0, 1);
}
static void check_reuse_write_wait(struct reuse_tcp* reuse,
struct waiting_tcp* first, struct waiting_tcp* last, size_t total)
{
size_t i, j;
struct waiting_tcp* w = reuse->write_wait_first;
struct waiting_tcp* n = NULL;
if(first) unit_assert(reuse->write_wait_first == first && !first->write_wait_prev);
if(last) unit_assert(reuse->write_wait_last == last && !last->write_wait_next);
/* check one way */
for(i=0; w; i++) {
unit_assert(i<total); /* otherwise we are looping */
unit_assert(w->write_wait_queued);
n = w->write_wait_next;
for(j=0; n; j++) {
unit_assert(j<total-i-1); /* otherwise we are looping */
unit_assert(n != w);
n = n->write_wait_next;
}
w = w->write_wait_next;
}
/* check the other way */
w = reuse->write_wait_last;
for(i=0; w; i++) {
unit_assert(i<total); /* otherwise we are looping */
unit_assert(w->write_wait_queued);
n = w->write_wait_prev;
for(j=0; n; j++) {
unit_assert(j<total-i-1); /* otherwise we are looping */
unit_assert(n != w);
n = n->write_wait_prev;
}
w = w->write_wait_prev;
}
}
/** clear the tcp waiting list */
static void reuse_write_wait_clear(struct reuse_tcp* reuse)
{
struct waiting_tcp* w = reuse->write_wait_first, *n = NULL;
if(!w) return;
unit_assert(reuse->write_wait_first);
unit_assert(reuse->write_wait_last);
while(w) {
n = w->write_wait_next;
w->write_wait_queued = 0;
w->write_wait_next = (struct waiting_tcp*)1; /* In purpose faux value */
w->write_wait_prev = (struct waiting_tcp*)1; /* In purpose faux value */
w = n;
}
reuse->write_wait_first = NULL;
reuse->write_wait_last = NULL;
}
/** check removal of the reuse_write_wait element on the given position of total
* elements */
static void check_reuse_write_wait_removal(int is_pop,
struct reuse_tcp* reuse, struct waiting_tcp* store,
size_t position, size_t total)
{
size_t i;
struct waiting_tcp* w;
reuse_write_wait_clear(reuse);
for(i=0; i<total; i++) {
reuse_write_wait_push_back(reuse, &store[i]);
}
check_reuse_write_wait(reuse, &store[0], &store[total-1], total);
if(is_pop) {
w = reuse_write_wait_pop(reuse);
} else {
w = reuse->write_wait_first;
for(i=0; i<position; i++) w = w->write_wait_next;
reuse_write_wait_remove(reuse, w);
}
unit_assert(!(w->write_wait_queued || w->write_wait_next || w->write_wait_prev));
if(position == 0 && total == 1) {
/* the list should be empty */
check_reuse_write_wait(reuse, NULL, NULL, total-1);
} else if(position == 0) {
/* first element should be gone */
check_reuse_write_wait(reuse, &store[1], &store[total-1], total-1);
} else if(position == total - 1) {
/* last element should be gone */
check_reuse_write_wait(reuse, &store[0], &store[total-2], total-1);
} else {
/* an element should be gone */
check_reuse_write_wait(reuse, &store[0], &store[total-1], total-1);
}
}
static void reuse_write_wait_test(void)
{
size_t i;
struct reuse_tcp reuse;
struct waiting_tcp store[MAX_TCP_WAITING_NODES];
struct waiting_tcp* w;
memset(&reuse, 0, sizeof(reuse));
memset(&store, 0, sizeof(store));
/* Check adding */
unit_show_func("services/outside_network.c", "reuse_write_wait_push_back");
for(i=0; i<MAX_TCP_WAITING_NODES; i++) {
w = &store[i];
reuse_write_wait_push_back(&reuse, w);
}
check_reuse_write_wait(&reuse, &store[0], w, MAX_TCP_WAITING_NODES);
/* Check removal */
unit_show_func("services/outside_network.c", "reuse_write_wait_remove");
check_reuse_write_wait_removal(0, &reuse, store, 2, 5);
check_reuse_write_wait_removal(0, &reuse, store, 1, 3);
check_reuse_write_wait_removal(0, &reuse, store, 0, 2);
check_reuse_write_wait_removal(0, &reuse, store, 1, 2);
check_reuse_write_wait_removal(0, &reuse, store, 0, 1);
/* Check pop */
unit_show_func("services/outside_network.c", "reuse_write_wait_pop");
check_reuse_write_wait_removal(1, &reuse, store, 0, 3);
check_reuse_write_wait_removal(1, &reuse, store, 0, 2);
check_reuse_write_wait_removal(1, &reuse, store, 0, 1);
}
void tcpreuse_test(void)
{
unit_show_feature("tcp_reuse");
tcpid_test();
tcp_reuse_tree_list_test();
waiting_tcp_list_test();
reuse_write_wait_test();
}

View File

@ -103,6 +103,15 @@ for input in $PRE/testdata/*.rpl $PRE/testdata/*.crpl; do
fi
fi
# detect if cachedb is needed
if echo $cleaninput | grep cachedb >/dev/null 2>&1; then
if grep "define USE_CACHEDB 1" $PRE/config.h >/dev/null 2>&1; then
: # CACHEDB is supported
else
continue
fi
fi
if test $do_valgrind = "yes"; then
echo
if (valgrind $VALGRIND_FLAGS $PRE/testbound -p $input >tmpout 2>&1;); then

View File

@ -28,6 +28,12 @@ if grep "define UB_ON_WINDOWS 1" ../../config.h; then
else
onwin=0
fi
# detect dnscrypt
if grep "define USE_DNSCRYPT 1" ../../config.h; then
with_dnscrypt=1
else
with_dnscrypt=0
fi
# test check of config files.
for f in bad.*; do
@ -37,6 +43,10 @@ for f in bad.*; do
echo "skipped on windows"
continue
fi
if test $f = "bad.proxy-and-dnscrypt" -a $with_dnscrypt -eq 0; then
echo "skipped; no DNSCRYPT support"
continue
fi
$PRE/unbound-checkconf $f
if test $? != 1; then

View File

@ -0,0 +1,6 @@
server:
interface: 127.0.0.1
proxy-protocol-port: 53
dnscrypt:
dnscrypt-enable: yes
dnscrypt-port: 53

View File

@ -0,0 +1,4 @@
server:
interface: 127.0.0.1
proxy-protocol-port: 53
https-port: 53

View File

@ -9,7 +9,7 @@ CmdDepends:
Depends:
Help:
Pre: acl_interface.pre
Post:
Post: acl_interface.post
Test: acl_interface.test
AuxFiles:
Passed:

View File

@ -0,0 +1,11 @@
# #-- acl_interface.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 $UNBOUND_PID
kill_pid $FWD_PID
kill_pid $STUB_PID

181
testdata/cachedb_servfail_cname.crpl vendored Normal file
View File

@ -0,0 +1,181 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
minimal-responses: no
;serve-expired: yes
module-config: "cachedb iterator"
cachedb:
backend: "testframe"
secret-seed: "testvalue"
stub-zone:
name: "."
stub-addr: 193.0.14.129
CONFIG_END
SCENARIO_BEGIN Test cachedb store and servfail reply from cname.
; the servfail reply should not overwrite the cache contents.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns2.example.com. IN A 1.2.3.5
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
foo.com. IN NS
SECTION AUTHORITY
foo.com. IN NS ns.example.com.
ENTRY_END
RANGE_END
; ns2.example.com.
RANGE_BEGIN 0 20
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns2.example.com., now failing
RANGE_BEGIN 20 100
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME foo.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA SERVFAIL
SECTION QUESTION
foo.example.com. IN A
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA SERVFAIL
SECTION QUESTION
ns2.example.com. IN A
SECTION ANSWER
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA SERVFAIL
SECTION QUESTION
ns2.example.com. IN AAAA
SECTION ANSWER
ENTRY_END
RANGE_END
; get and entry in cache, to make it expired.
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; get the answer for it
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; it is now expired
STEP 20 TIME_PASSES ELAPSE 20
; get a servfail in cache for the destination
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
foo.example.com. IN A
ENTRY_END
STEP 40 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA SERVFAIL
SECTION QUESTION
foo.example.com. IN A
ENTRY_END
; the query is now a CNAME to servfail.
; there is a valid, but expired, entry in cache.
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 60 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA SERVFAIL
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME foo.example.com.
ENTRY_END
SCENARIO_END

View File

@ -1 +0,0 @@
rm -f K* piece1 base expired notyetincepted trust-anchors dnssec-failures.test.signed dnskey-failures.test.signed nsec-failures.test.signed rrsig-failures.test.signed

View File

@ -0,0 +1,7 @@
dnskey-failures.test. 3600 IN SOA ns.dnskey-failures.test. hostmaster.dnskey-failures.test. 1 14400 1800 2419200 300
dnskey-failures.test. 3600 IN RRSIG SOA 13 2 3600 20010201000000 20001230000000 45928 dnskey-failures.test. NKixvGKa0WHSI8oE5THI1hjm5nExVkryUmW15VoNZ3pwqUYexGWLIlfuYsTaDE5GVEtPpSKbA+PlYDk19EsLNQ==
dnskey-failures.test. 3600 IN A 192.0.2.1
dnskey-failures.test. 3600 IN RRSIG A 13 2 3600 20010201000000 20001230000000 45928 dnskey-failures.test. FCEvbVL3TkzO7jWeOz7E/A3Q64QkpegVazS4OL+ybxN2o8OzXdCJN3QbCGdFP26/Rbj089ThDCZ0+OormAk1dw==
dnskey-failures.test. 3600 IN RRSIG DNSKEY 13 2 3600 20010201000000 20001230000000 45928 dnskey-failures.test. pEjWVsJbFiQBvwNGV3v0nVirMJDOYKXqC4IX9dFuRTnoWSb95anvB08pgaZ1ie+thk6YC1fX2fUTRKRFr3vHnA==
dnskey-failures.test. 300 IN NSEC dnskey-failures.test. A SOA RRSIG NSEC DNSKEY
dnskey-failures.test. 300 IN RRSIG NSEC 13 2 300 20010201000000 20001230000000 45928 dnskey-failures.test. /vAazBDetA5+np+fE7V6f9W+faEQT3ETGueNNhFPjUsPF1dU9Gglu4PZ15fWOxsk0DPWHNmTMF70ZCGQJ2k+fw==

View File

@ -0,0 +1,25 @@
dnssec-failures.test. 3600 IN SOA ns.dnssec-failures.test. hostmaster.dnssec-failures.test. 1 14400 1800 2419200 300
dnssec-failures.test. 3600 IN RRSIG SOA 13 2 3600 20010201000000 20001230000000 53876 dnssec-failures.test. K37BIR/jLR4tN1JtTx3MwzgozslvnFtwUquCSfiBykCcKIv6wErSI9Gnw/tjH0tXrLI1eoLa5oWkgtxy0KKybg==
dnssec-failures.test. 3600 IN NS ns.dnssec-failures.test.
dnssec-failures.test. 3600 IN RRSIG NS 13 2 3600 20010201000000 20001230000000 53876 dnssec-failures.test. JP6mYQORwnwwv+2q9UxpeeaVs5/171y3lyc1FKAY3FHmFqjd4Uo0byW8jgk/BrJyVkaDeZbjvuZq+BED0codpw==
dnssec-failures.test. 3600 IN DNSKEY 257 3 13 mx6xe39HZrYCpyC+9YmquHIf1WdWYaDqOfcpXg2Gtv5VJGS/WSO14txlUoKjYCldyRwcg9wT6JAwikpkzWS6UQ== ;{id = 53876 (ksk), size = 256b}
dnssec-failures.test. 3600 IN RRSIG DNSKEY 13 2 3600 20010201000000 20001230000000 53876 dnssec-failures.test. F760TrogHIBkenX7nGr6LEvocTcGAZamfAaiftIkwprBp21/LZ+qotGsFu9YWsxlGqB3KAINXYATjS6AEJfGEQ==
dnssec-failures.test. 300 IN NSEC expired.dnssec-failures.test. NS SOA RRSIG NSEC DNSKEY
dnssec-failures.test. 300 IN RRSIG NSEC 13 2 300 20010201000000 20001230000000 53876 dnssec-failures.test. Zk+RW0mbLSzwvSYuNQJhNdd4XmtQv47CiLtHbqOyS8/xt5Pt87T0v1UxnCkZAlA+VTEWbJkasq06ER1wMuTetA==
expired.dnssec-failures.test. 300 IN RRSIG NSEC 13 3 300 20010201000000 20001230000000 53876 dnssec-failures.test. UAhzOVumQZ2PVspwJS5NyOjZypIaQXfHMiXGEUYaZ161IfQdB3coBx2vF8MHdqbePOl6Z4oa51ltITMlBL+Stw==
missingrrsigs.dnssec-failures.test. 3600 IN TXT "Signatures missing"
missingrrsigs.dnssec-failures.test. 300 IN NSEC notyetincepted.dnssec-failures.test. TXT RRSIG NSEC
missingrrsigs.dnssec-failures.test. 300 IN RRSIG NSEC 13 3 300 20010201000000 20001230000000 53876 dnssec-failures.test. 4phKld6eMt4cxA4w6I1i29uAbdfbwFrkpRGLBWwerUgDbOdDwUm1de6t4QhBys7DtoZb3wIS+DLJYjBNbz7Sig==
notyetincepted.dnssec-failures.test. 300 IN RRSIG NSEC 13 3 300 20010201000000 20001230000000 53876 dnssec-failures.test. ix6Gg9uUZ0A56IQXbDJuBQ3vIm6QipuvzQTKd2wF6kZuEW/53wuy4ROBDIQ4IgnQD17vG8tJNeDOCfj0hh8+dQ==
ns.dnssec-failures.test. 3600 IN A 192.0.2.1
ns.dnssec-failures.test. 3600 IN RRSIG A 13 3 3600 20010201000000 20001230000000 53876 dnssec-failures.test. PbcykgJEHG218vCkj9pD8W5JVqyCD9VRNOy3SHqCTvWGVAApasdZ7n5wzNVpHdKrqlTpyLwf6z6vv4NMYbEQdw==
ns.dnssec-failures.test. 300 IN NSEC sigsinvalid.dnssec-failures.test. A RRSIG NSEC
ns.dnssec-failures.test. 300 IN RRSIG NSEC 13 3 300 20010201000000 20001230000000 53876 dnssec-failures.test. SEO+C116gcmI0sY4lnIM4DQrUxqyaGIIqlvhxyGrzF9jJopRZB8gflQcYPy5qhIwGZJoEMB+SO4er4LCaS8NwA==
sigsinvalid.dnssec-failures.test. 3600 IN TXT "Signatures INVALID"
sigsinvalid.dnssec-failures.test. 3600 IN RRSIG TXT 13 3 3600 20010201000000 20001230000000 53876 dnssec-failures.test. 3XFjjPt+UyY4ZIj8PAINTtOTh7sk4OIAO5akFDQhqgB/Wv6f7dWdqvl8Y2RIqdh0WQz+nGPRMktS8exA3FKW4Q==
sigsinvalid.dnssec-failures.test. 300 IN NSEC dnssec-failures.test. TXT RRSIG NSEC
sigsinvalid.dnssec-failures.test. 300 IN RRSIG NSEC 13 3 300 20010201000000 20001230000000 53876 dnssec-failures.test. gmft6HYmqZalLwmdnuWBqJod3JD5fRoGqiwYXVFxySm2bHPvz8J9xSe7RdTSONXPUc+7mE8IHYff/gGW7gctqw==
expired.dnssec-failures.test. 3600 IN TXT "Expired"
expired.dnssec-failures.test. 3600 IN RRSIG TXT 13 3 3600 20001230000000 20001201000000 53876 dnssec-failures.test. 8zosYGmmGGcGcBuWaf3oL3TE/hpKDrddtm7ZQGndjmqkZ8CVg6RwFb+8YLqcG5du3Si0rmTuZId+qBOV/pnViA==
notyetincepted.dnssec-failures.test. 3600 IN TXT "Not yet incepted"
notyetincepted.dnssec-failures.test. 3600 IN RRSIG TXT 13 3 3600 20010201000000 20010103000000 53876 dnssec-failures.test. lmk0+oEdnnKa1oujIsMeimuElrKvrUSlBknsfSNqOo07VxJxT2R4qkKc95oiEmeSWHcVTOrXxEhtl4kAAactPg==

View File

@ -1,21 +1,28 @@
#!/usr/bin/env bash
# create oudated zones
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom dnssec-failures.test`
echo $CSK
# This script was used to generate the broken signed zones used for testing.
echo ". IN DS 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d" | \
cat $CSK.ds - > bogus/trust-anchors
# Override the current date; it is used in Unbound's configuration also.
NOW=20010101
# differentiate for MacOS with "gdate"
DATE=date
which gdate > /dev/null 2>&1 && DATE=gdate
ONEMONTHAGO=`$DATE -d 'now - 1 month' +%Y%m%d`
YESTERDAY=`$DATE -d 'now - 2 days' +%Y%m%d`
TOMORROW=`$DATE -d 'now + 2 days' +%Y%m%d`
ONEMONTHAGO=`$DATE -d "$NOW - 1 month" +%Y%m%d`
ONEMONTH=`$DATE -d "$NOW + 1 month" +%Y%m%d`
YESTERDAY=`$DATE -d "$NOW - 2 days" +%Y%m%d`
TOMORROW=`$DATE -d "$NOW + 2 days" +%Y%m%d`
ldns-signzone -i $YESTERDAY -f - bogus/dnssec-failures.test $CSK | \
# Root trust anchor
echo ". IN DS 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d" > bogus/trust-anchors
# create oudated zones
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom dnssec-failures.test`
echo $CSK
cat $CSK.ds >> bogus/trust-anchors
ldns-signzone -i $YESTERDAY -e $ONEMONTH -f - bogus/dnssec-failures.test $CSK | \
grep -v '^missingrrsigs\.dnssec-failures\.test\..*IN.*RRSIG.*TXT' | \
sed 's/Signatures invalid/Signatures INVALID/g' | \
grep -v '^notyetincepted\.dnssec-failures\.test\..*IN.*TXT' | \
@ -25,7 +32,7 @@ ldns-signzone -i $YESTERDAY -f - bogus/dnssec-failures.test $CSK | \
ldns-signzone -i $ONEMONTHAGO -e $YESTERDAY -f - bogus/dnssec-failures.test $CSK | \
grep -v '[ ]NSEC[ ]' | \
grep '^expired\.dnssec-failures\.test\..*IN.*TXT' > expired
ldns-signzone -i $TOMORROW -f - bogus/dnssec-failures.test $CSK | \
ldns-signzone -i $TOMORROW -e $ONEMONTH -f - bogus/dnssec-failures.test $CSK | \
grep -v '[ ]NSEC[ ]' | \
grep '^notyetincepted\.dnssec-failures\.test\..*IN.*TXT' > notyetincepted
@ -33,34 +40,35 @@ cat base expired notyetincepted > bogus/dnssec-failures.test.signed
# cleanup old zone keys
rm -f $CSK.*
# create zone with DNSKEY missing
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom dnskey-failures.test`
echo $CSK
cat $CSK.ds >> bogus/trust-anchors
ldns-signzone -f tmp.signed bogus/dnskey-failures.test $CSK
ldns-signzone -i $YESTERDAY -e $ONEMONTH -f tmp.signed bogus/dnskey-failures.test $CSK
grep -v ' DNSKEY ' tmp.signed > bogus/dnskey-failures.test.signed
# cleanup old zone keys
rm -f $CSK.*
# create zone with NSEC missing
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom nsec-failures.test`
echo $CSK
cat $CSK.ds >> bogus/trust-anchors
ldns-signzone -f tmp.signed bogus/nsec-failures.test $CSK
ldns-signzone -i $YESTERDAY -e $ONEMONTH -f tmp.signed bogus/nsec-failures.test $CSK
grep -v ' NSEC ' tmp.signed > bogus/nsec-failures.test.signed
# cleanup old zone keys
rm -f $CSK.*
# create zone with RRSIGs missing
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom rrsig-failures.test`
echo $CSK
cat $CSK.ds >> bogus/trust-anchors
ldns-signzone -f tmp.signed bogus/rrsig-failures.test $CSK
ldns-signzone -i $YESTERDAY -e $ONEMONTH -f tmp.signed bogus/rrsig-failures.test $CSK
grep -v ' RRSIG ' tmp.signed > bogus/rrsig-failures.test.signed
# cleanup

View File

@ -0,0 +1,7 @@
nsec-failures.test. 3600 IN SOA ns.nsec-failures.test. hostmaster.nsec-failures.test. 1 14400 1800 2419200 300
nsec-failures.test. 3600 IN RRSIG SOA 13 2 3600 20010201000000 20001230000000 12342 nsec-failures.test. ZdnRF2uI0IDJsHTXsd4TclX9gUEkxjp19LykHuI3DaCKe3bY8uTETta8i73hlKWJWeRjmgQojIsi9tBlivOwjQ==
nsec-failures.test. 3600 IN A 192.0.2.1
nsec-failures.test. 3600 IN RRSIG A 13 2 3600 20010201000000 20001230000000 12342 nsec-failures.test. /JccCtWkuQgSF81gv6DPsxaicmlJoGAhVpCpR4JGgVz3tZMhIp+iXUGeI+CkBofw9G/MK66Hk937JRmMh9UTvQ==
nsec-failures.test. 3600 IN DNSKEY 257 3 13 41tJnzHY0o3WKid0ZsIo6S5SJdC1JiW0H/KizsAD2phHdi1AIDiBclL+nG2lKvPjMoX2hcMfd8h9DfU99HR3kg== ;{id = 12342 (ksk), size = 256b}
nsec-failures.test. 3600 IN RRSIG DNSKEY 13 2 3600 20010201000000 20001230000000 12342 nsec-failures.test. Y23xTzxdqQBjFsWLlqCRgPKT7raPcP0lAy2tR8trW5+vUAhBePXdVixp4AjoxEqXsLLalAtnJnc4QgH7+HO6PA==
nsec-failures.test. 300 IN RRSIG NSEC 13 2 300 20010201000000 20001230000000 12342 nsec-failures.test. KfpncqGIzIPNB2ExkH22/z0jAPmq8jTTjDkLte29iKqR9t3bSZlcS0MQ2QB7Z6tgks8fo7Zpc9+BvaDq7Y6ONg==

View File

@ -0,0 +1,4 @@
rrsig-failures.test. 3600 IN SOA ns.rrsig-failures.test. hostmaster.rrsig-failures.test. 1 14400 1800 2419200 300
rrsig-failures.test. 3600 IN A 192.0.2.1
rrsig-failures.test. 3600 IN DNSKEY 257 3 13 rIMJ4/qnOb91GuxKzAYiCdPNdEtUhyt+mi1Jz+NPP0rJQdGOhXr37LpctEiKK4isabCXcwYlVtFdDPopa4RufA== ;{id = 13838 (ksk), size = 256b}
rrsig-failures.test. 300 IN NSEC rrsig-failures.test. A SOA RRSIG NSEC DNSKEY

5
testdata/ede.tdir/bogus/trust-anchors vendored Normal file
View File

@ -0,0 +1,5 @@
. IN DS 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d
dnssec-failures.test. IN DS 53876 13 2 e0207223d847e0d8f3bd2afcf887f727178777a94563b94e1d0be8ca2f070d9a
dnskey-failures.test. IN DS 45928 13 2 9295d5c0d9296599809ce968f994a974d4da7752266ee124ead4ce980c006c20
nsec-failures.test. IN DS 12342 13 2 b0a994fe4ff12a706b2a47a794601b254a8d28e040832ad6e39e96dbf7736ca2
rrsig-failures.test. IN DS 13838 13 2 b083d59d2e7ac370e1103bc5ada2a921e4e65745ea8550350b6fcb57eba9f917

View File

@ -11,6 +11,7 @@ server:
val-log-level: 2
trust-anchor-file: "bogus/trust-anchors"
val-override-date: "20010101020202"
module-config: "respip validator iterator"

View File

@ -4,7 +4,9 @@
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
PRE="../.."
. ../common.sh
get_random_port 2
UNBOUND_PORT=$RND_PORT
UNBOUND_PORT2=$(($RND_PORT + 1))
@ -16,11 +18,7 @@ sed -e 's/@PORT\@/'$UNBOUND_PORT'/' < ede.conf > temp.conf
sed -e 's/@PORT2\@/'$UNBOUND_PORT2'/' < temp.conf > ub.conf
sed -e 's/@PORT2\@/'$UNBOUND_PORT2'/' < ede-auth.conf > ub2.conf
# create broken dnssec zone
bogus/make-broken-zone.sh
# 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
@ -30,8 +28,6 @@ $PRE/unbound -d -c ub2.conf > unbound2.log 2>&1 &
UNBOUND_PID2=$!
echo "UNBOUND_PID2=$UNBOUND_PID2" >> .tpkg.var.test
cat .tpkg.var.test
wait_unbound_up unbound.log
wait_unbound_up unbound2.log

View File

@ -176,36 +176,7 @@ SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
; due to ordering of answer packets, this is still outstanding, remove it
STEP 21 CHECK_OUT_QUERY
ENTRY_BEGIN
ADJUST copy_id
MATCH qname qtype
REPLY QR
SECTION QUESTION
ns.example.com IN AAAA
ENTRY_END
; some more recursion needed.
; to finish the NS query
STEP 40 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
. IN NS
ENTRY_END
STEP 41 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION AUTHORITY
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
; let (possible) outstanding queries finish resolving
STEP 21 TRAFFIC
SCENARIO_END

View File

@ -155,7 +155,7 @@ ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
REPLY QR AA NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION AUTHORITY
@ -188,36 +188,7 @@ SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
; due to ordering of answer packets, this is still outstanding, remove it
STEP 21 CHECK_OUT_QUERY
ENTRY_BEGIN
ADJUST copy_id
MATCH qname qtype
REPLY QR
SECTION QUESTION
ns.example.com IN AAAA
ENTRY_END
; some more recursion needed.
; to finish the NS query
STEP 40 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
. IN NS
ENTRY_END
STEP 41 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION AUTHORITY
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
; let (possible) outstanding queries finish resolving
STEP 21 TRAFFIC
SCENARIO_END

138
testdata/iter_auth_tc.rpl vendored Normal file
View File

@ -0,0 +1,138 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: "no"
minimal-responses: no
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test authoritative response with erroneous TC flag
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
ns.example.com. IN A
SECTION ANSWER
ns.example.com. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION ANSWER
SECTION AUTHORITY
example.com. IN NS ns.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
; erroneous TC flag here
REPLY QR TC NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA SERVFAIL
SECTION QUESTION
www.example.com. IN A
ENTRY_END
SCENARIO_END

View File

@ -164,11 +164,11 @@ a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
ns.example.org. IN A
example.org. IN A
SECTION AUTHORITY
example.org. NS ns.example.net.
example.org. NS ns.example.org.

View File

@ -216,14 +216,7 @@ example.com. IN NS ns.example.net.
;ns.example.net IN A 1.2.3.44
ENTRY_END
; due to ordering of answer packets, this is still outstanding, remove it
STEP 21 CHECK_OUT_QUERY
ENTRY_BEGIN
ADJUST copy_id
MATCH qname qtype
REPLY QR
SECTION QUESTION
ns.example.net IN AAAA
ENTRY_END
; let (possible) outstanding queries finish resolving
STEP 21 TRAFFIC
SCENARIO_END

View File

@ -0,0 +1,34 @@
server:
verbosity: 5
num-threads: 1
interface: 127.0.0.1@@PORT@
interface: 127.0.0.1@@PROXYPORT@
interface: 127.0.0.1@@PROXYTLSPORT@
interface: @INTERFACE_ALLOW_ADDR@@@PORT@
interface: @INTERFACE_ALLOW_ADDR@@@PROXYPORT@
interface: @INTERFACE_ALLOW_ADDR@@@PROXYTLSPORT@
interface: @INTERFACE_REFUSE_ADDR@@@PORT@
interface: @INTERFACE_REFUSE_ADDR@@@PROXYPORT@
interface: @INTERFACE_REFUSE_ADDR@@@PROXYTLSPORT@
proxy-protocol-port: @PROXYPORT@
proxy-protocol-port: @PROXYTLSPORT@
tls-port: @PROXYTLSPORT@
use-syslog: no
directory: .
pidfile: "unbound.pid"
chroot: ""
username: ""
do-not-query-localhost: no
tls-service-key: "unbound_server.key"
tls-service-pem: "unbound_server.pem"
# 127.0.0.0/8 is allowed by default.
access-control: @CLIENT_ADDR_ALLOW@/32 allow
access-control: @CLIENT_ADDR_REFUSE@/32 refuse
access-control: @CLIENT_ADDR_ALLOW6@/128 allow
access-control: @CLIENT_ADDR_REFUSE6@/128 refuse
access-control: @INTERFACE_ALLOW_ADDR@/32 allow
forward-zone:
name: "."
forward-addr: "127.0.0.1@@TOPORT@"

View File

@ -0,0 +1,16 @@
BaseName: proxy_protocol
Version: 1.0
Description: Test proxy protocol
CreationDate: Mon Mar 14 16:17:00 CET 2022
Maintainer: Yorgos Thessalonikefs
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: proxy_protocol.pre
Post: proxy_protocol.post
Test: proxy_protocol.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,12 @@
# #-- proxy_protocol.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
cat unbound.log
exit 0

View File

@ -0,0 +1,66 @@
# #-- proxy_protocol.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
PRE="../.."
. ../common.sh
# This test uses the unshare utility
if test ! -x "`which unshare 2>&1`"; then
skip_test "no unshare (from util-linux package) available, skip test"
fi
get_make
(cd $PRE; $MAKE streamtcp)
get_random_port 4
UNBOUND_PORT=$RND_PORT
FWD_PORT=$(($RND_PORT + 1))
PROXY_PORT=$(($RND_PORT + 2))
PROXY_TLS_PORT=$(($RND_PORT + 3))
INTERFACE_ALLOW=eth123
INTERFACE_ALLOW_ADDR=10.1.2.3
INTERFACE_REFUSE=eth234
INTERFACE_REFUSE_ADDR=10.2.3.4
CLIENT_ADDR_ALLOW=1.2.3.4
CLIENT_ADDR_ALLOW6=2001:db8::cafe:cafe
CLIENT_ADDR_REFUSE=5.6.7.8
CLIENT_ADDR_REFUSE6=2001:db8::dead:beef
# make config file
sed \
-e 's/@PORT\@/'$UNBOUND_PORT'/' \
-e 's/@TOPORT\@/'$FWD_PORT'/' \
-e 's/@PROXYPORT\@/'$PROXY_PORT'/' \
-e 's/@PROXYTLSPORT\@/'$PROXY_TLS_PORT'/' \
-e 's/@INTERFACE_ALLOW_ADDR\@/'$INTERFACE_ALLOW_ADDR'/' \
-e 's/@INTERFACE_REFUSE_ADDR\@/'$INTERFACE_REFUSE_ADDR'/' \
-e 's/@CLIENT_ADDR_ALLOW\@/'$CLIENT_ADDR_ALLOW'/' \
-e 's/@CLIENT_ADDR_ALLOW6\@/'$CLIENT_ADDR_ALLOW6'/' \
-e 's/@CLIENT_ADDR_REFUSE\@/'$CLIENT_ADDR_REFUSE'/' \
-e 's/@CLIENT_ADDR_REFUSE6\@/'$CLIENT_ADDR_REFUSE6'/' \
< proxy_protocol.conf > ub.conf
if test -x "`which bash`"; then
shell="bash"
else
shell="sh"
fi
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
echo "PROXY_PORT=$PROXY_PORT" >> .tpkg.var.test
echo "PROXY_TLS_PORT=$PROXY_TLS_PORT" >> .tpkg.var.test
echo "INTERFACE_ALLOW=$INTERFACE_ALLOW" >> .tpkg.var.test
echo "INTERFACE_ALLOW_ADDR=$INTERFACE_ALLOW_ADDR" >> .tpkg.var.test
echo "INTERFACE_REFUSE=$INTERFACE_REFUSE" >> .tpkg.var.test
echo "INTERFACE_REFUSE_ADDR=$INTERFACE_REFUSE_ADDR" >> .tpkg.var.test
echo "CLIENT_ADDR_ALLOW=$CLIENT_ADDR_ALLOW" >> .tpkg.var.test
echo "CLIENT_ADDR_ALLOW6=$CLIENT_ADDR_ALLOW6" >> .tpkg.var.test
echo "CLIENT_ADDR_REFUSE=$CLIENT_ADDR_REFUSE" >> .tpkg.var.test
echo "CLIENT_ADDR_REFUSE6=$CLIENT_ADDR_REFUSE6" >> .tpkg.var.test
echo "shell=$shell" >> .tpkg.var.test

View File

@ -0,0 +1,12 @@
# #-- proxy_protocol.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="../.."
. ../common.sh
# Run the scenario in an unshared namespace
unshare -rUn $shell proxy_protocol.test.scenario
exit $?

View File

@ -0,0 +1,193 @@
# #-- proxy_protocol.test.scenario --#
# 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="../.."
. ../common.sh
ip addr add 127.0.0.1 dev lo
ip link set lo up
ip link add $INTERFACE_ALLOW type dummy
ip addr add $INTERFACE_ALLOW_ADDR dev $INTERFACE_ALLOW
ip link set $INTERFACE_ALLOW up
ip link add $INTERFACE_REFUSE type dummy
ip addr add $INTERFACE_REFUSE_ADDR dev $INTERFACE_REFUSE
ip link set $INTERFACE_REFUSE up
# start forwarder in the background
get_ldns_testns
$LDNS_TESTNS -p $FWD_PORT proxy_protocol.testns >fwd.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
# start unbound in the background
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd.log
wait_unbound_up unbound.log
# call streamtcp and check return value
do_streamtcp () {
$PRE/streamtcp $* A IN >outfile 2>&1
if test "$?" -ne 0; then
echo "exit status not OK"
echo "> cat logfiles"
cat outfile
cat unbound.log
echo "Not OK"
exit 1
fi
}
send_query () {
server=$1
client=$2
prot=$3
query=$4
echo -n "> query $query to $server"
port=$UNBOUND_PORT
if test ! -z "$client"; then
port=$PROXY_PORT
fi
case $prot in
-u)
echo -n " (over UDP)"
;;
-s)
echo -n " (over TLS)"
port=$PROXY_TLS_PORT
;;
*)
echo -n " (over TCP)"
esac
if test ! -z "$client"; then
echo -n " ($client proxied)"
fi
echo
do_streamtcp $prot -f $server@$port $client $query
#cat outfile
}
expect_answer () {
#query=$1
#answer=$2
if grep "$query" outfile | grep "$answer"; then
echo "content OK"
echo
else
echo "> cat logfiles"
cat outfile
cat unbound.log
echo "result contents not OK"
exit 1
fi
}
expect_refuse () {
if grep "rcode: REFUSE" outfile; then
echo "content OK"
echo
else
echo "> cat logfiles"
cat outfile
cat unbound.log
echo "result contents not OK"
exit 1
fi
}
# Start the test
# Query without PROXYv2
# Client localhost
# Expect the result back
server=127.0.0.1
client=""
query="two.example.net."
answer="2.2.2.2"
for prot in "-u" ""; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW should be allowed
# Expect the result back
server=127.0.0.1
client="-p $CLIENT_ADDR_ALLOW@1234"
query="one.example.net."
answer="1.1.1.1"
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW6 should be allowed
# Expect the result back
server=127.0.0.1
client="-p $CLIENT_ADDR_ALLOW6@1234"
query="one.example.net."
answer="1.1.1.1"
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_REFUSE should be refused
# Expect the REFUSE back
server=127.0.0.1
client="-p $CLIENT_ADDR_REFUSE"
query="one.example.net."
answer=""
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_refuse
done
# Query with PROXYv2
# Client $CLIENT_ADDR_REFUSE6 should be refused
# Expect the REFUSE back
server=127.0.0.1
client="-p $CLIENT_ADDR_REFUSE6"
query="one.example.net."
answer=""
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_refuse
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW should be allowed; proxy source address should be allowed
# Expect the result back
server=$INTERFACE_ALLOW_ADDR
client="-p $CLIENT_ADDR_ALLOW@1234"
query="one.example.net."
answer="1.1.1.1"
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW should be allowed; proxy source address should be refused
# Expect the REFUSE back
server=$INTERFACE_REFUSE_ADDR
client="-p $CLIENT_ADDR_ALLOW@1234"
query="one.example.net."
answer=""
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_refuse
done
echo "OK"
exit 0

View File

@ -0,0 +1,23 @@
; nameserver test file
$ORIGIN example.net.
$TTL 3600
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR RD RA NOERROR
ADJUST copy_id
SECTION QUESTION
one IN A
SECTION ANSWER
one IN A 1.1.1.1
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR RD RA NOERROR
ADJUST copy_id
SECTION QUESTION
two IN A
SECTION ANSWER
two IN A 2.2.2.2
ENTRY_END

View File

@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG5AIBAAKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI
0x41iG32a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+Nqq
GRS7XVQ24vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Z
uh9MDgotaBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8K
WaBe1ca4TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5
FzUReSXZuTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xP
q6O9UPj4+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XL
A5UoZgRzXgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP
7kFZSngxdy1+A/bNAgMBAAECggGBALpTOIqQwVg4CFBylL/a8K1IWJTI/I65sklf
XxYL7G7SB2HlEJ//z+E+F0+S4Vlao1vyLQ5QkgE82pAUB8FoMWvY1qF0Y8A5wtm6
iZSGk4OLK488ZbT8Ii9i+AGKgPe2XbVxsJwj8N4k7Zooqec9hz73Up8ATEWJkRz7
2u7oMGG4z91E0PULA64dOi3l/vOQe5w/Aa+CwVbAWtI05o7kMvQEBMDJn6C7CByo
MB5op9wueJMnz7PM7hns+U7Dy6oE4ljuolJUy51bDzFWwoM54cRoQqLFNHd8JVQj
WxldCkbfF43iyprlsEcUrTyUjtdA+ZeiG39vg/mtdmgNpGmdupHJZQvSuG8IcVlz
O+eMSeQS1QXPD6Ik8UK4SU0h+zOl8xIWtRrsxQuh4fnTN40udm/YUWl/6gOebsBI
IrVLlKGqJSfB3tMjpCRqdTzJ0dA9keVpkqm2ugZkxEf1+/efq/rFIQ2pUBLCqNTN
qpNqruK8y8FphP30I2uI4Ej2UIB8AQKBwQDd2Yptj2FyDyaXCycsyde0wYkNyzGU
dRnzdibfHnMZwjgTjwAwgIUBVIS8H0/z7ZJQKN7osJfddMrtjJtYYUk9g/dCpHXs
bNh2QSoWah3FdzNGuWd0iRf9+LFxhjAAMo/FS8zFJAJKrFsBdCGTfFUMdsLC0bjr
YjiWBuvV72uKf8XIZX5KIZruKdWBBcWukcb21R1UDyFYyXRBsly5XHaIYKZql3km
7pV7MKWO0IYgHbHIqGUqPQlzZ/lkunS1jKECgcEA23wHffD6Ou9/x3okPx2AWpTr
gh8rgqbyo6hQkBW5Y90Wz824cqaYebZDaBR/xlVx/YwjKkohv8Bde2lpH/ZxRZ1Z
5Sk2s6GJ/vU0L9RsJZgCgj4L6Coal1NMxuZtCXAlnOpiCdxSZgfqbshbTVz30KsG
ZJG361Cua1ScdAHxlZBxT52/1Sm0zRC2hnxL7h4qo7Idmtzs40LAJvYOKekR0pPN
oWeJfra7vgx/jVNvMFWoOoSLpidVO4g+ot4ery6tAoHAdW3rCic1C2zdnmH28Iw+
s50l8Lk3mz+I5wgJd1zkzCO0DxZIoWPGA3g7cmCYr6N3KRsZMs4W9NAXgjpFGDkW
zYsG3K21BdpvkdjYcFjnPVjlOXB2RIc0vehf9Jl02wXoeCSxVUDEPcaRvWk9RJYx
ZpGOchUU7vNkxHURbIJ4yCzuAi9G8/Jp0dsu+kaV5tufF5SjG5WOrzKjaQsCbdN1
oqaWMCHRrTvov/Z2C+xwsptFOdN5CSyZzg6hQiI4GMlBAoHAXyb6KINcOEi0YMp3
BFXJ23tMTnEs78tozcKeipigcsbaqORK3omS+NEnj+uzKUzJyl4CsMbKstK2tFYS
mSTCHqgE3PBtIpsZtEqhgUraR8IK9GPpzZDTTl9ynZgwFTNlWw3RyuyVXF56J+T8
kCGJ3hEHCHqT/ZRQyX85BKIDFhA0z4tYKxWVqIFiYBNq56R0X9tMMmMs36mEnF93
7Ht6mowxTZQRa7nU0qOgeKh/P7ki4Zus3y+WJ+T9IqahLtlRAoHBAIhqMrcxSAB8
RpB9jukJlAnidw2jCMPgrFE8tP0khhVvGrXMldxAUsMKntDIo8dGCnG1KTcWDI0O
jepvSPHSsxVLFugL79h0eVIS5z4huW48i9xgU8VlHdgAcgEPIAOFcOw2BCu/s0Vp
O+MM/EyUOdo3NsibB3qc/GJI6iNBYS7AljYEVo6rXo5V/MZvZUF4vClen6Obzsre
MTTb+4sJjfqleWuvr1XNMeu2mBfXBQkWGZP1byBK0MvD/aQ2PWq92A==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqzCCAhMCFBHWXeQ6ZIa9QcQbXLFfC6tj+KA+MA0GCSqGSIb3DQEBCwUAMBIx
EDAOBgNVBAMMB3VuYm91bmQwHhcNMjAwNzA4MTMzMjI5WhcNNDAwMzI1MTMzMjI5
WjASMRAwDgYDVQQDDAd1bmJvdW5kMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
igKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI0x41iG32
a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+NqqGRS7XVQ2
4vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Zuh9MDgot
aBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8KWaBe1ca4
TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5FzUReSXZ
uTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xPq6O9UPj4
+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XLA5UoZgRz
XgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP7kFZSngx
dy1+A/bNAgMBAAEwDQYJKoZIhvcNAQELBQADggGBABunf93MKaCUHiZgnoOTinsW
84/EgInrgtKzAyH+BhnKkJOhhR0kkIAx5d9BpDlaSiRTACFon9moWCgDIIsK/Ar7
JE0Kln9cV//wiiNoFU0O4mnzyGUIMvlaEX6QHMJJQYvL05+w/3AAcf5XmMJtR5ca
fJ8FqvGC34b2WxX9lTQoyT52sRt+1KnQikiMEnEyAdKktMG+MwKsFDdOwDXyZhZg
XZhRrfX3/NVJolqB6EahjWIGXDeKuSSKZVtCyib6LskyeMzN5lcRfvubKDdlqFVF
qlD7rHBsKhQUWK/IO64mGf7y/de+CgHtED5vDvr/p2uj/9sABATfbrOQR3W/Of25
sLBj4OEfrJ7lX8hQgFaxkMI3x6VFT3W8dTCp7xnQgb6bgROWB5fNEZ9jk/gjSRmD
yIU+r0UbKe5kBk/CmZVFXL2TyJ92V5NYEQh8V4DGy19qZ6u/XKYyNJL4ocs35GGe
CA8SBuyrmdhx38h1RHErR2Skzadi1S7MwGf1y431fQ==
-----END CERTIFICATE-----

View File

@ -37,7 +37,12 @@
import os
def init(id, cfg):
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
scripts=[]
s = cfg.python_script
while s != None:
scripts.append(s.str)
s = s.next
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, scripts))
return True
def deinit(id):

View File

@ -0,0 +1,16 @@
server:
verbosity: 4
# 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: "example.com"
stub-addr: "127.0.0.1@@TOPORT@"

View File

@ -0,0 +1,16 @@
BaseName: stub_auth_tc
Version: 1.0
Description: Authority reply with erroneous TC in TCP
CreationDate: Mon Oct 3 09:11:32 CEST 2022
Maintainer: dr. W.C.A. Wijngaards
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: stub_auth_tc.pre
Post: stub_auth_tc.post
Test: stub_auth_tc.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,11 @@
# #-- stub_auth_tc.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

View File

@ -0,0 +1,31 @@
# #-- stub_auth_tc.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_auth_tc.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_auth_tc.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

View File

@ -0,0 +1,26 @@
# #-- stub_auth_tc.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 www.example.com."
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "> check answer"
if grep "SERVFAIL" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
if grep "flags:" outfile | grep " tc "; then
echo "Not OK, TC flag in output"
exit 1
fi
exit 0

View File

@ -0,0 +1,26 @@
; nameserver test file
$ORIGIN example.com.
$TTL 3600
ENTRY_BEGIN
MATCH opcode qtype qname UDP
REPLY QR AA TC NOERROR
ADJUST copy_id
SECTION QUESTION
www IN A
SECTION ANSWER
www IN A 10.20.30.40
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname TCP
; erroneous TC flag here.
REPLY QR AA TC NOERROR
ADJUST copy_id
SECTION QUESTION
www IN A
SECTION ANSWER
www IN A 10.20.30.40
www IN A 10.20.30.41
www IN A 10.20.30.42
ENTRY_END

View File

@ -794,6 +794,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_SIZET_NONZERO("pad-responses-block-size:", pad_responses_block_size)
else S_YNO("pad-queries:", pad_queries)
else S_SIZET_NONZERO("pad-queries-block-size:", pad_queries_block_size)
else S_STRLIST("proxy-protocol-port:", proxy_protocol_port)
#ifdef USE_IPSECMOD
else S_YNO("ipsecmod-enabled:", ipsecmod_enabled)
else S_YNO("ipsecmod-ignore-bogus:", ipsecmod_ignore_bogus)
@ -1270,6 +1271,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "pad-queries", pad_queries)
else O_DEC(opt, "pad-queries-block-size", pad_queries_block_size)
else O_LS2(opt, "edns-client-strings", edns_client_strings)
else O_LST(opt, "proxy-protocol-port", proxy_protocol_port)
#ifdef USE_IPSECMOD
else O_YNO(opt, "ipsecmod-enabled", ipsecmod_enabled)
else O_YNO(opt, "ipsecmod-ignore-bogus", ipsecmod_ignore_bogus)
@ -1650,6 +1652,7 @@ config_delete(struct config_file* cfg)
config_delstrlist(cfg->python_script);
config_delstrlist(cfg->dynlib_file);
config_deldblstrlist(cfg->edns_client_strings);
config_delstrlist(cfg->proxy_protocol_port);
#ifdef USE_IPSECMOD
free(cfg->ipsecmod_hook);
config_delstrlist(cfg->ipsecmod_whitelist);
@ -2647,3 +2650,35 @@ int cfg_has_https(struct config_file* cfg)
}
return 0;
}
/** see if interface is PROXYv2, its port number == the proxy port number */
int
if_is_pp2(const char* ifname, const char* port,
struct config_strlist* proxy_protocol_port)
{
struct config_strlist* s;
char* p = strchr(ifname, '@');
for(s = proxy_protocol_port; s; s = s->next) {
if(p && atoi(p+1) == atoi(s->str))
return 1;
if(!p && atoi(port) == atoi(s->str))
return 1;
}
return 0;
}
/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */
int
if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port)
{
#ifdef USE_DNSCRYPT
return ((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
(!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
#else
(void)ifname;
(void)port;
(void)dnscrypt_port;
return 0;
#endif
}

View File

@ -114,6 +114,8 @@ struct config_file {
int do_tcp_keepalive;
/** tcp keepalive timeout, in msec */
int tcp_keepalive_timeout;
/** proxy protocol ports */
struct config_strlist* proxy_protocol_port;
/** private key file for dnstcp-ssl service (enabled if not NULL) */
char* ssl_service_key;
@ -1329,6 +1331,12 @@ int if_is_https(const char* ifname, const char* port, int https_port);
*/
int cfg_has_https(struct config_file* cfg);
/** see if interface is PROXYv2, its port number == the proxy port number */
int if_is_pp2(const char* ifname, const char* port,
struct config_strlist* proxy_protocol_port);
/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */
int if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port);
#ifdef USE_LINUX_IP_LOCAL_PORT_RANGE
#define LINUX_IP_LOCAL_PORT_RANGE_PATH "/proc/sys/net/ipv4/ip_local_port_range"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -564,6 +564,7 @@ edns-client-string{COLON} { YDVAR(2, VAR_EDNS_CLIENT_STRING) }
edns-client-string-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) }
nsid{COLON} { YDVAR(1, VAR_NSID ) }
ede{COLON} { YDVAR(1, VAR_EDE ) }
proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* Quoted strings. Strip leading and ending quotes */

File diff suppressed because it is too large Load Diff

View File

@ -385,7 +385,8 @@ extern int yydebug;
VAR_INTERFACE_VIEW = 586, /* VAR_INTERFACE_VIEW */
VAR_INTERFACE_TAG = 587, /* VAR_INTERFACE_TAG */
VAR_INTERFACE_TAG_ACTION = 588, /* VAR_INTERFACE_TAG_ACTION */
VAR_INTERFACE_TAG_DATA = 589 /* VAR_INTERFACE_TAG_DATA */
VAR_INTERFACE_TAG_DATA = 589, /* VAR_INTERFACE_TAG_DATA */
VAR_PROXY_PROTOCOL_PORT = 590 /* VAR_PROXY_PROTOCOL_PORT */
};
typedef enum yytokentype yytoken_kind_t;
#endif
@ -726,6 +727,7 @@ extern int yydebug;
#define VAR_INTERFACE_TAG 587
#define VAR_INTERFACE_TAG_ACTION 588
#define VAR_INTERFACE_TAG_DATA 589
#define VAR_PROXY_PROTOCOL_PORT 590
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@ -735,7 +737,7 @@ union YYSTYPE
char* str;
#line 739 "util/configparser.h"
#line 741 "util/configparser.h"
};
typedef union YYSTYPE YYSTYPE;

View File

@ -196,6 +196,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_RPZ_SIGNAL_NXDOMAIN_RA VAR_INTERFACE_AUTOMATIC_PORTS VAR_EDE
%token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG
%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
%token VAR_PROXY_PROTOCOL_PORT
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -324,8 +325,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_edns_client_string_opcode | server_nsid |
server_zonemd_permissive_mode | server_max_reuse_tcp_queries |
server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
server_interface_automatic_ports | server_ede
server_interface_automatic_ports | server_ede |
server_proxy_protocol_port
;
stubstart: VAR_STUB_ZONE
{
@ -2828,6 +2829,13 @@ server_ede: VAR_EDE STRING_ARG
free($2);
}
;
server_proxy_protocol_port: VAR_PROXY_PROTOCOL_PORT STRING_ARG
{
OUTYY(("P(server_proxy_protocol_port:%s)\n", $2));
if(!cfg_strlist_insert(&cfg_parser->cfg->proxy_protocol_port, $2))
yyerror("out of memory");
}
;
stub_name: VAR_NAME STRING_ARG
{
OUTYY(("P(name:%s)\n", $2));

View File

@ -1144,7 +1144,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
*/
else if (memcmp( cookie_hash( hash, server_cookie
, &repinfo->addr
, &repinfo->remote_addr
, cfg->cookie_secret)
, rdata_ptr + 16 , 8 ) == 0) {
@ -1171,8 +1171,8 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
server_cookie[10] = 0; /* Reserved */
server_cookie[11] = 0; /* Reserved */
sldns_write_uint32(server_cookie + 12, now);
cookie_hash( hash, server_cookie
, &repinfo->addr, cfg->cookie_secret);
cookie_hash( hash, server_cookie, &repinfo->remote_addr
, cfg->cookie_secret);
memcpy(server_cookie + 16, hash, 8);
if (!edns_opt_list_append( &edns->opt_list_out
, LDNS_EDNS_COOKIE

File diff suppressed because it is too large Load Diff

View File

@ -128,10 +128,11 @@ struct comm_reply {
/** the comm_point with fd to send reply on to. */
struct comm_point* c;
/** the address (for UDP based communication) */
struct sockaddr_storage addr;
struct sockaddr_storage remote_addr;
/** length of address */
socklen_t addrlen;
/** return type 0 (none), 4(IP4), 6(IP6) */
socklen_t remote_addrlen;
/** return type 0 (none), 4(IP4), 6(IP6)
* used only with listen_type_udp_ancil* */
int srctype;
/* DnsCrypt context */
#ifdef USE_DNSCRYPT
@ -155,6 +156,13 @@ struct comm_reply {
pktinfo;
/** max udp size for udp packets */
size_t max_udp_size;
/* if set, the request came through a proxy */
int is_proxied;
/** the client address
* the same as remote_addr if not proxied */
struct sockaddr_storage client_addr;
/** the original address length */
socklen_t client_addrlen;
};
/**
@ -278,6 +286,19 @@ struct comm_point {
/** variable with type of socket, UDP,TCP-accept,TCP,pipe */
type;
/* -------- PROXYv2 ------- */
/** if set, PROXYv2 is expected on this connection */
int pp2_enabled;
/** header state for the PROXYv2 header (for TCP) */
enum {
/** no header encounter yet */
pp2_header_none = 0,
/** read the static part of the header */
pp2_header_init,
/** read the full header */
pp2_header_done
} pp2_header_state;
/* ---------- Behaviour ----------- */
/** if set the connection is NOT closed on delete. */
int do_not_close;
@ -496,8 +517,9 @@ struct ub_event_base* comm_base_internal(struct comm_base* b);
* Create an UDP comm point. Calls malloc.
* setups the structure with the parameters you provide.
* @param base: in which base to alloc the commpoint.
* @param fd : file descriptor of open UDP socket.
* @param fd: file descriptor of open UDP socket.
* @param buffer: shared buffer by UDP sockets from this thread.
* @param pp2_enabled: if the comm point will support PROXYv2.
* @param callback: callback function pointer.
* @param callback_arg: will be passed to your callback function.
* @param socket: and opened socket properties will be passed to your callback function.
@ -505,7 +527,7 @@ struct ub_event_base* comm_base_internal(struct comm_base* b);
* Sets timeout to NULL. Turns off TCP options.
*/
struct comm_point* comm_point_create_udp(struct comm_base* base,
int fd, struct sldns_buffer* buffer,
int fd, struct sldns_buffer* buffer, int pp2_enabled,
comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket);
/**
@ -513,8 +535,9 @@ struct comm_point* comm_point_create_udp(struct comm_base* base,
* Uses recvmsg instead of recv to get udp message.
* setups the structure with the parameters you provide.
* @param base: in which base to alloc the commpoint.
* @param fd : file descriptor of open UDP socket.
* @param fd: file descriptor of open UDP socket.
* @param buffer: shared buffer by UDP sockets from this thread.
* @param pp2_enabled: if the comm point will support PROXYv2.
* @param callback: callback function pointer.
* @param callback_arg: will be passed to your callback function.
* @param socket: and opened socket properties will be passed to your callback function.
@ -522,7 +545,7 @@ struct comm_point* comm_point_create_udp(struct comm_base* base,
* Sets timeout to NULL. Turns off TCP options.
*/
struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
int fd, struct sldns_buffer* buffer,
int fd, struct sldns_buffer* buffer, int pp2_enabled,
comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket);
/**
@ -544,6 +567,7 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* 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 pp2_enabled: if the comm point will support PROXYv2.
* @param callback: callback function pointer for TCP handlers.
* @param callback_arg: will be passed to your callback function.
* @param socket: and opened socket properties will be passed to your callback function.
@ -557,7 +581,7 @@ struct comm_point* comm_point_create_tcp(struct comm_base* base,
uint32_t http_max_streams, char* http_endpoint,
struct tcl_list* tcp_conn_limit,
size_t bufsize, struct sldns_buffer* spoolbuf,
enum listen_type port_type,
enum listen_type port_type, int pp2_enabled,
comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket);
/**

139
util/proxy_protocol.c Normal file
View File

@ -0,0 +1,139 @@
/*
* util/proxy_protocol.c - event notification
*
* Copyright (c) 2022, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains PROXY protocol functions.
*/
#include "config.h"
#include "util/log.h"
#include "util/proxy_protocol.h"
int
pp2_write_to_buf(struct sldns_buffer* buf, struct sockaddr_storage* src,
int stream)
{
int af;
if(!src) return 0;
af = (int)((struct sockaddr_in*)src)->sin_family;
if(sldns_buffer_remaining(buf) <
PP2_HEADER_SIZE + (af==AF_INET?12:36)) {
return 0;
}
/* sig */
sldns_buffer_write(buf, PP2_SIG, PP2_SIG_LEN);
/* version and command */
sldns_buffer_write_u8(buf, (PP2_VERSION << 4) | PP2_CMD_PROXY);
if(af==AF_INET) {
/* family and protocol */
sldns_buffer_write_u8(buf,
(PP2_AF_INET<<4) |
(stream?PP2_PROT_STREAM:PP2_PROT_DGRAM));
/* length */
sldns_buffer_write_u16(buf, 12);
/* src addr */
sldns_buffer_write(buf,
&((struct sockaddr_in*)src)->sin_addr.s_addr, 4);
/* dst addr */
sldns_buffer_write_u32(buf, 0);
/* src port */
sldns_buffer_write(buf,
&((struct sockaddr_in*)src)->sin_port, 2);
/* dst port */
sldns_buffer_write_u16(buf, 0);
} else {
/* family and protocol */
sldns_buffer_write_u8(buf,
(PP2_AF_INET6<<4) |
(stream?PP2_PROT_STREAM:PP2_PROT_DGRAM));
/* length */
sldns_buffer_write_u16(buf, 36);
/* src addr */
sldns_buffer_write(buf,
&((struct sockaddr_in6*)src)->sin6_addr, 16);
/* dst addr */
sldns_buffer_set_at(buf,
sldns_buffer_position(buf), 0, 16);
sldns_buffer_skip(buf, 16);
/* src port */
sldns_buffer_write(buf,
&((struct sockaddr_in6*)src)->sin6_port, 2);
/* dst port */
sldns_buffer_write_u16(buf, 0);
}
return 1;
}
struct pp2_header*
pp2_read_header(struct sldns_buffer* buf)
{
size_t size;
struct pp2_header* header = (struct pp2_header*)sldns_buffer_begin(buf);
/* Try to fail all the unsupported cases first. */
if(sldns_buffer_remaining(buf) < PP2_HEADER_SIZE) {
log_err("proxy_protocol: not enough space for header");
return NULL;
}
/* Check for PROXYv2 header */
if(memcmp(header, PP2_SIG, PP2_SIG_LEN) != 0 ||
((header->ver_cmd & 0xF0)>>4) != PP2_VERSION) {
log_err("proxy_protocol: could not match PROXYv2 header");
return NULL;
}
/* Check the length */
size = PP2_HEADER_SIZE + ntohs(header->len);
if(sldns_buffer_remaining(buf) < size) {
log_err("proxy_protocol: not enough space for header");
return NULL;
}
/* Check for supported commands */
if((header->ver_cmd & 0xF) != PP2_CMD_LOCAL &&
(header->ver_cmd & 0xF) != PP2_CMD_PROXY) {
log_err("proxy_protocol: unsupported command");
return NULL;
}
/* Check for supported family and protocol */
if(header->fam_prot != 0x00 /* AF_UNSPEC|UNSPEC */ &&
header->fam_prot != 0x11 /* AF_INET|STREAM */ &&
header->fam_prot != 0x12 /* AF_INET|DGRAM */ &&
header->fam_prot != 0x21 /* AF_INET6|STREAM */ &&
header->fam_prot != 0x22 /* AF_INET6|DGRAM */) {
log_err("proxy_protocol: unsupported family and protocol");
return NULL;
}
/* We have a correct header */
return header;
}

131
util/proxy_protocol.h Normal file
View File

@ -0,0 +1,131 @@
/*
* util/proxy_protocol.h - PROXY protocol
*
* Copyright (c) 2022, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains PROXY protocol structs and functions.
* Only v2 is supported. TLVs are not currently supported.
*/
#ifndef PROXY_PROTOCOL_H
#define PROXY_PROTOCOL_H
#include "sldns/sbuffer.h"
/** PROXYv2 minimum header size */
#define PP2_HEADER_SIZE 16
/** PROXYv2 header signature */
#define PP2_SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
#define PP2_SIG_LEN 12
/** PROXYv2 version */
#define PP2_VERSION 0x2
/**
* PROXYv2 command.
*/
enum pp2_command {
PP2_CMD_LOCAL = 0x0,
PP2_CMD_PROXY = 0x1
};
/**
* PROXYv2 address family.
*/
enum pp2_af {
PP2_AF_UNSPEC = 0x0,
PP2_AF_INET = 0x1,
PP2_AF_INET6 = 0x2,
PP2_AF_UNIX = 0x3
};
/**
* PROXYv2 protocol.
*/
enum pp2_protocol {
PP2_PROT_UNSPEC = 0x0,
PP2_PROT_STREAM = 0x1,
PP2_PROT_DGRAM = 0x2
};
/**
* PROXYv2 header.
*/
struct pp2_header {
uint8_t sig[PP2_SIG_LEN];
uint8_t ver_cmd;
uint8_t fam_prot;
uint16_t len;
union {
struct { /* for TCP/UDP over IPv4, len = 12 */
uint32_t src_addr;
uint32_t dst_addr;
uint16_t src_port;
uint16_t dst_port;
} addr4;
struct { /* for TCP/UDP over IPv6, len = 36 */
uint8_t src_addr[16];
uint8_t dst_addr[16];
uint16_t src_port;
uint16_t dst_port;
} addr6;
struct { /* for AF_UNIX sockets, len = 216 */
uint8_t src_addr[108];
uint8_t dst_addr[108];
} addru;
} addr;
};
/**
* Write a PROXYv2 header at the current position of the buffer.
* @param buf: the buffer to write to.
* @param src: the source address.
* @param stream: if the protocol is stream or datagram.
* @return 1 on success, 0 on failure.
*/
int pp2_write_to_buf(struct sldns_buffer* buf, struct sockaddr_storage* src,
int stream);
/**
* Read a PROXYv2 header from the current position of the buffer.
* It does initial validation and returns a pointer to the buffer position on
* success.
* @param buf: the buffer to read from.
* @return the pointer to the buffer position on success, NULL on error.
*/
struct pp2_header* pp2_read_header(struct sldns_buffer* buf);
#endif /* PROXY_PROTOCOL_H */