mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
Merge branch 'master' into dnsoverquic
This commit is contained in:
commit
19868cc37f
@ -747,7 +747,7 @@ msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/uti
|
||||
msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
|
||||
msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
|
||||
@ -802,7 +802,7 @@ iter_priv.lo iter_priv.o: $(srcdir)/iterator/iter_priv.c config.h $(srcdir)/iter
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h
|
||||
iter_resptype.lo iter_resptype.o: $(srcdir)/iterator/iter_resptype.c config.h \
|
||||
$(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iterator.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h
|
||||
|
@ -265,11 +265,11 @@ cachedb_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
cachedb_env->enabled = 1;
|
||||
if(env->cfg->serve_expired_reply_ttl)
|
||||
if(env->cfg->serve_expired && env->cfg->serve_expired_reply_ttl)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-reply-ttl is set but not working for data "
|
||||
"originating from the external cache; 0 TLL is used for those.");
|
||||
if(env->cfg->serve_expired_client_timeout)
|
||||
"originating from the external cache; 0 TTL is used for those.");
|
||||
if(env->cfg->serve_expired && env->cfg->serve_expired_client_timeout)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-client-timeout is set but not working for "
|
||||
"data originating from the external cache; expired data are used "
|
||||
|
@ -59,11 +59,28 @@ struct redis_moddata {
|
||||
const char* server_path; /* server's unix path, or "", NULL if unused */
|
||||
const char* server_password; /* server's AUTH password, or "", NULL if unused */
|
||||
struct timeval timeout; /* timeout for connection setup and commands */
|
||||
int logical_db; /* the redis logical database to use */
|
||||
};
|
||||
|
||||
static redisReply* redis_command(struct module_env*, struct cachedb_env*,
|
||||
const char*, const uint8_t*, size_t);
|
||||
|
||||
static void
|
||||
moddata_clean(struct redis_moddata** moddata) {
|
||||
if(!moddata || !*moddata)
|
||||
return;
|
||||
if((*moddata)->ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < (*moddata)->numctxs; i++) {
|
||||
if((*moddata)->ctxs[i])
|
||||
redisFree((*moddata)->ctxs[i]);
|
||||
}
|
||||
free((*moddata)->ctxs);
|
||||
}
|
||||
free(*moddata);
|
||||
*moddata = NULL;
|
||||
}
|
||||
|
||||
static redisContext*
|
||||
redis_connect(const struct redis_moddata* moddata)
|
||||
{
|
||||
@ -97,10 +114,21 @@ redis_connect(const struct redis_moddata* moddata)
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
if(moddata->logical_db > 0) {
|
||||
redisReply* rep;
|
||||
rep = redisCommand(ctx, "SELECT %d", moddata->logical_db);
|
||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
||||
log_err("failed to set logical database (%d)",
|
||||
moddata->logical_db);
|
||||
freeReplyObject(rep);
|
||||
goto fail;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
verbose(VERB_OPS, "Connection to Redis established");
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
if(ctx)
|
||||
redisFree(ctx);
|
||||
return NULL;
|
||||
@ -117,14 +145,13 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
moddata = calloc(1, sizeof(struct redis_moddata));
|
||||
if(!moddata) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
moddata->numctxs = env->cfg->num_threads;
|
||||
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->ctxs) {
|
||||
log_err("out of memory");
|
||||
free(moddata);
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
/* note: server_host is a shallow reference to configured string.
|
||||
* we don't have to free it in this module. */
|
||||
@ -134,8 +161,15 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
moddata->server_password = env->cfg->redis_server_password;
|
||||
moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||
moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
|
||||
for(i = 0; i < moddata->numctxs; i++)
|
||||
moddata->ctxs[i] = redis_connect(moddata);
|
||||
moddata->logical_db = env->cfg->redis_logical_db;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(moddata);
|
||||
if(!ctx) {
|
||||
log_err("redis_init: failed to init redis");
|
||||
goto fail;
|
||||
}
|
||||
moddata->ctxs[i] = ctx;
|
||||
}
|
||||
cachedb_env->backend_data = moddata;
|
||||
if(env->cfg->redis_expire_records) {
|
||||
redisReply* rep = NULL;
|
||||
@ -148,7 +182,7 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
redis_reply_type = rep->type;
|
||||
freeReplyObject(rep);
|
||||
@ -160,11 +194,14 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
moddata_clean(&moddata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -175,18 +212,7 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
(void)env;
|
||||
|
||||
verbose(VERB_OPS, "Redis deinitialization");
|
||||
|
||||
if(!moddata)
|
||||
return;
|
||||
if(moddata->ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
if(moddata->ctxs[i])
|
||||
redisFree(moddata->ctxs[i]);
|
||||
}
|
||||
free(moddata->ctxs);
|
||||
}
|
||||
free(moddata);
|
||||
moddata_clean(&moddata);
|
||||
}
|
||||
|
||||
/*
|
||||
|
607
configure
vendored
607
configure
vendored
@ -4607,450 +4607,186 @@ fi
|
||||
|
||||
default_cflags=yes
|
||||
fi
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}gcc; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_CC+:} false; then :
|
||||
case $ac_cv_prog_cc_stdc in #(
|
||||
no) :
|
||||
ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #(
|
||||
*) :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
|
||||
$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
|
||||
if ${ac_cv_prog_cc_c99+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$CC"; then
|
||||
ac_cv_prog_CC="$CC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
CC=$ac_cv_prog_CC
|
||||
if test -n "$CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
|
||||
$as_echo "$CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test -z "$ac_cv_prog_CC"; then
|
||||
ac_ct_CC=$CC
|
||||
# Extract the first word of "gcc", so it can be a program name with args.
|
||||
set dummy gcc; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_ac_ct_CC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$ac_ct_CC"; then
|
||||
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_CC="gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
ac_ct_CC=$ac_cv_prog_ac_ct_CC
|
||||
if test -n "$ac_ct_CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
|
||||
$as_echo "$ac_ct_CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
if test "x$ac_ct_CC" = x; then
|
||||
CC=""
|
||||
else
|
||||
case $cross_compiling:$ac_tool_warned in
|
||||
yes:)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
ac_tool_warned=yes ;;
|
||||
esac
|
||||
CC=$ac_ct_CC
|
||||
fi
|
||||
else
|
||||
CC="$ac_cv_prog_CC"
|
||||
fi
|
||||
|
||||
if test -z "$CC"; then
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}cc; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_CC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$CC"; then
|
||||
ac_cv_prog_CC="$CC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}cc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
CC=$ac_cv_prog_CC
|
||||
if test -n "$CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
|
||||
$as_echo "$CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
fi
|
||||
if test -z "$CC"; then
|
||||
# Extract the first word of "cc", so it can be a program name with args.
|
||||
set dummy cc; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_CC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$CC"; then
|
||||
ac_cv_prog_CC="$CC" # Let the user override the test.
|
||||
else
|
||||
ac_prog_rejected=no
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
|
||||
ac_prog_rejected=yes
|
||||
continue
|
||||
fi
|
||||
ac_cv_prog_CC="cc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
if test $ac_prog_rejected = yes; then
|
||||
# We found a bogon in the path, so make sure we never use it.
|
||||
set dummy $ac_cv_prog_CC
|
||||
shift
|
||||
if test $# != 0; then
|
||||
# We chose a different compiler from the bogus one.
|
||||
# However, it has the same basename, so the bogon will be chosen
|
||||
# first if we set CC to just the basename; use the full file name.
|
||||
shift
|
||||
ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
CC=$ac_cv_prog_CC
|
||||
if test -n "$CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
|
||||
$as_echo "$CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test -z "$CC"; then
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
for ac_prog in cl.exe
|
||||
do
|
||||
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_CC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$CC"; then
|
||||
ac_cv_prog_CC="$CC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
CC=$ac_cv_prog_CC
|
||||
if test -n "$CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
|
||||
$as_echo "$CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$CC" && break
|
||||
done
|
||||
fi
|
||||
if test -z "$CC"; then
|
||||
ac_ct_CC=$CC
|
||||
for ac_prog in cl.exe
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_ac_ct_CC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$ac_ct_CC"; then
|
||||
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_CC="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
ac_ct_CC=$ac_cv_prog_ac_ct_CC
|
||||
if test -n "$ac_ct_CC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
|
||||
$as_echo "$ac_ct_CC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$ac_ct_CC" && break
|
||||
done
|
||||
|
||||
if test "x$ac_ct_CC" = x; then
|
||||
CC=""
|
||||
else
|
||||
case $cross_compiling:$ac_tool_warned in
|
||||
yes:)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
ac_tool_warned=yes ;;
|
||||
esac
|
||||
CC=$ac_ct_CC
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "no acceptable C compiler found in \$PATH
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
|
||||
# Provide some information about the compiler.
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
|
||||
set X $ac_compile
|
||||
ac_compiler=$2
|
||||
for ac_option in --version -v -V -qversion; do
|
||||
{ { ac_try="$ac_compiler $ac_option >&5"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
|
||||
ac_status=$?
|
||||
if test -s conftest.err; then
|
||||
sed '10a\
|
||||
... rest of stderr output deleted ...
|
||||
10q' conftest.err >conftest.er1
|
||||
cat conftest.er1 >&5
|
||||
fi
|
||||
rm -f conftest.er1 conftest.err
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }
|
||||
done
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
|
||||
$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
|
||||
if ${ac_cv_c_compiler_gnu+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
ac_cv_prog_cc_c99=no
|
||||
ac_save_CC=$CC
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
// Check varargs macros. These examples are taken from C99 6.10.3.5.
|
||||
#define debug(...) fprintf (stderr, __VA_ARGS__)
|
||||
#define showlist(...) puts (#__VA_ARGS__)
|
||||
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
|
||||
static void
|
||||
test_varargs_macros (void)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
choke me
|
||||
int x = 1234;
|
||||
int y = 5678;
|
||||
debug ("Flag");
|
||||
debug ("X = %d\n", x);
|
||||
showlist (The first, second, and third items.);
|
||||
report (x>y, "x is %d but y is %d", x, y);
|
||||
}
|
||||
|
||||
// Check long long types.
|
||||
#define BIG64 18446744073709551615ull
|
||||
#define BIG32 4294967295ul
|
||||
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
|
||||
#if !BIG_OK
|
||||
your preprocessor is broken;
|
||||
#endif
|
||||
#if BIG_OK
|
||||
#else
|
||||
your preprocessor is broken;
|
||||
#endif
|
||||
static long long int bignum = -9223372036854775807LL;
|
||||
static unsigned long long int ubignum = BIG64;
|
||||
|
||||
;
|
||||
struct incomplete_array
|
||||
{
|
||||
int datasize;
|
||||
double data[];
|
||||
};
|
||||
|
||||
struct named_init {
|
||||
int number;
|
||||
const wchar_t *name;
|
||||
double average;
|
||||
};
|
||||
|
||||
typedef const char *ccp;
|
||||
|
||||
static inline int
|
||||
test_restrict (ccp restrict text)
|
||||
{
|
||||
// See if C++-style comments work.
|
||||
// Iterate through items via the restricted pointer.
|
||||
// Also check for declarations in for loops.
|
||||
for (unsigned int i = 0; *(text+i) != '\0'; ++i)
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_compiler_gnu=yes
|
||||
else
|
||||
ac_compiler_gnu=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
ac_cv_c_compiler_gnu=$ac_compiler_gnu
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
|
||||
$as_echo "$ac_cv_c_compiler_gnu" >&6; }
|
||||
if test $ac_compiler_gnu = yes; then
|
||||
GCC=yes
|
||||
else
|
||||
GCC=
|
||||
fi
|
||||
ac_test_CFLAGS=${CFLAGS+set}
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
|
||||
$as_echo_n "checking whether $CC accepts -g... " >&6; }
|
||||
if ${ac_cv_prog_cc_g+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_save_c_werror_flag=$ac_c_werror_flag
|
||||
ac_c_werror_flag=yes
|
||||
ac_cv_prog_cc_g=no
|
||||
CFLAGS="-g"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
// Check varargs and va_copy.
|
||||
static void
|
||||
test_varargs (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
va_list args_copy;
|
||||
va_copy (args_copy, args);
|
||||
|
||||
const char *str;
|
||||
int number;
|
||||
float fnumber;
|
||||
|
||||
while (*format)
|
||||
{
|
||||
switch (*format++)
|
||||
{
|
||||
case 's': // string
|
||||
str = va_arg (args_copy, const char *);
|
||||
break;
|
||||
case 'd': // int
|
||||
number = va_arg (args_copy, int);
|
||||
break;
|
||||
case 'f': // float
|
||||
fnumber = va_arg (args_copy, double);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end (args_copy);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_cv_prog_cc_g=yes
|
||||
else
|
||||
CFLAGS=""
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
// Check bool.
|
||||
_Bool success = false;
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
// Check restrict.
|
||||
if (test_restrict ("String literal") == 0)
|
||||
success = true;
|
||||
char *restrict newvar = "Another string";
|
||||
|
||||
// Check varargs.
|
||||
test_varargs ("s, d' f .", "string", 65, 34.234);
|
||||
test_varargs_macros ();
|
||||
|
||||
// Check flexible array members.
|
||||
struct incomplete_array *ia =
|
||||
malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
|
||||
ia->datasize = 10;
|
||||
for (int i = 0; i < ia->datasize; ++i)
|
||||
ia->data[i] = i * 1.234;
|
||||
|
||||
// Check named initializers.
|
||||
struct named_init ni = {
|
||||
.number = 34,
|
||||
.name = L"Test wide string",
|
||||
.average = 543.34343,
|
||||
};
|
||||
|
||||
ni.number = 58;
|
||||
|
||||
int dynamic_array[ni.number];
|
||||
dynamic_array[ni.number - 1] = 543;
|
||||
|
||||
// work around unused variable warnings
|
||||
return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
|
||||
|| dynamic_array[ni.number - 1] != 543);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
|
||||
do
|
||||
CC="$ac_save_CC $ac_arg"
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_cv_prog_cc_c99=$ac_arg
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext
|
||||
test "x$ac_cv_prog_cc_c99" != "xno" && break
|
||||
done
|
||||
rm -f conftest.$ac_ext
|
||||
CC=$ac_save_CC
|
||||
|
||||
fi
|
||||
# AC_CACHE_VAL
|
||||
case "x$ac_cv_prog_cc_c99" in
|
||||
x)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
|
||||
$as_echo "none needed" >&6; } ;;
|
||||
xno)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
|
||||
$as_echo "unsupported" >&6; } ;;
|
||||
*)
|
||||
CC="$CC $ac_cv_prog_cc_c99"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
|
||||
$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
|
||||
esac
|
||||
if test "x$ac_cv_prog_cc_c99" != xno; then :
|
||||
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
|
||||
else
|
||||
ac_c_werror_flag=$ac_save_c_werror_flag
|
||||
CFLAGS="-g"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_cv_prog_cc_g=yes
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
ac_c_werror_flag=$ac_save_c_werror_flag
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
|
||||
$as_echo "$ac_cv_prog_cc_g" >&6; }
|
||||
if test "$ac_test_CFLAGS" = set; then
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
elif test $ac_cv_prog_cc_g = yes; then
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="-g -O2"
|
||||
else
|
||||
CFLAGS="-g"
|
||||
fi
|
||||
else
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="-O2"
|
||||
else
|
||||
CFLAGS=
|
||||
fi
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
|
||||
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
|
||||
if ${ac_cv_prog_cc_c89+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
@ -5137,14 +4873,31 @@ $as_echo "unsupported" >&6; } ;;
|
||||
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
|
||||
esac
|
||||
if test "x$ac_cv_prog_cc_c89" != xno; then :
|
||||
|
||||
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
|
||||
else
|
||||
ac_cv_prog_cc_stdc=no
|
||||
fi
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5
|
||||
$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; }
|
||||
if ${ac_cv_prog_cc_stdc+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
fi
|
||||
|
||||
case $ac_cv_prog_cc_stdc in #(
|
||||
no) :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
|
||||
$as_echo "unsupported" >&6; } ;; #(
|
||||
'') :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
|
||||
$as_echo "none needed" >&6; } ;; #(
|
||||
*) :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5
|
||||
$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;;
|
||||
esac
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $CC dependency flag" >&5
|
||||
|
@ -280,7 +280,7 @@ ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
|
||||
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||
default_cflags=yes
|
||||
fi
|
||||
AC_PROG_CC
|
||||
m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_STDC])
|
||||
ACX_DEPFLAG
|
||||
ACX_DETERMINE_EXT_FLAGS_UNBOUND
|
||||
|
||||
|
@ -590,7 +590,7 @@ ssl_read_line(RES* res, char* buf, size_t max)
|
||||
while(1) {
|
||||
ssize_t rr = recv(res->fd, buf+len, 1, 0);
|
||||
if(rr <= 0) {
|
||||
if(rr == 0) {
|
||||
if(rr == 0 && len != 0) {
|
||||
buf[len] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/proxy_protocol.h"
|
||||
#include "util/tube.h"
|
||||
#include "util/edns.h"
|
||||
#include "util/timeval_func.h"
|
||||
@ -2319,6 +2320,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker->env.cfg->stat_interval);
|
||||
worker_restart_timer(worker);
|
||||
}
|
||||
pp_init(&sldns_write_uint16, &sldns_write_uint32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,63 @@
|
||||
11 October 2023: George
|
||||
- Fix #850: [FR] Ability to use specific database in Redis, with new
|
||||
redis-logical-db configuration option.
|
||||
|
||||
11 October 2023: Wouter
|
||||
- Fix #949: "could not create control compt".
|
||||
- Fix that cachedb does not warn when serve-expired is disabled about
|
||||
use of serve-expired-reply-ttl and serve-expired-client-timeout.
|
||||
- Fix for #949: Fix pythonmod/ubmodule-tst.py for Python 3.x.
|
||||
|
||||
10 October 2023: George
|
||||
- Fix infinite loop when reading multiple lines of input on a broken
|
||||
remote control socket. Addesses #947 and #948.
|
||||
|
||||
9 October 2023: Wouter
|
||||
- Fix edns subnet so that queries with a source prefix of zero cause
|
||||
the recursor send no edns subnet option to the upstream.
|
||||
- Fix that printout of EDNS options shows the EDNS cookie option by
|
||||
name.
|
||||
|
||||
4 October 2023: Wouter
|
||||
- Fix #946: Forwarder returns servfail on upstream response noerror no
|
||||
data.
|
||||
|
||||
3 October 2023: George
|
||||
- Merge #881: Generalise the proxy protocol code.
|
||||
|
||||
2 October 2023: George
|
||||
- Fix misplaced comment.
|
||||
|
||||
22 September 2023: Wouter
|
||||
- Fix #942: 1.18.0 libunbound DNS regression when built without
|
||||
OpenSSL.
|
||||
|
||||
18 September 2023: Wouter
|
||||
- Fix rpz tcp-only action with rpz triggers nsdname and nsip.
|
||||
|
||||
15 September 2023: Wouter
|
||||
- Merge #936: Check for c99 with autoconf versions prior to 2.70.
|
||||
- Fix to remove two c99 notations.
|
||||
|
||||
14 September 2023: Wouter
|
||||
- Fix authority zone answers for obscured DNAMEs and delegations.
|
||||
|
||||
8 September 2023: Wouter
|
||||
- Fix send of udp retries when ENOBUFS is returned. It stops looping
|
||||
and also waits for the condition to go away. Reported by Florian
|
||||
Obser.
|
||||
|
||||
7 September 2023: Wouter
|
||||
- Fix to scrub resource records of type A and AAAA that have an
|
||||
inappropriate size. They are removed from responses.
|
||||
- Fix to move msgparse_rrset_remove_rr code to util/msgparse.c.
|
||||
- Fix to add EDE text when RRs have been removed due to length.
|
||||
- Fix to set ede match in unit test for rr length removal.
|
||||
- Fix to print EDE text in readable form in output logs.
|
||||
|
||||
6 September 2023: Wouter
|
||||
- Merge #931: Prevent warnings from -Wmissing-prototypes.
|
||||
|
||||
31 August 2023: Wouter
|
||||
- Fix autoconf 2.69 warnings in configure.
|
||||
- Fix #927: unbound 1.18.0 make test error. Fix make test without SHA1.
|
||||
|
@ -1240,6 +1240,8 @@ remote-control:
|
||||
# redis-timeout: 100
|
||||
# # set timeout on redis records based on DNS response TTL
|
||||
# redis-expire-records: no
|
||||
# # redis logical database to use, 0 is the default database.
|
||||
# redis-logical-db: 0
|
||||
|
||||
# IPSet
|
||||
# Add specify domain into set via ipset.
|
||||
|
@ -2719,6 +2719,17 @@ Unbound is configured with \fBserve-expired\fR and \fBserve-expired-ttl\fR is 0,
|
||||
this option is internally reverted to "no". Redis SETEX support is required
|
||||
for this option (Redis >= 2.0.0).
|
||||
This option defaults to no.
|
||||
.TP
|
||||
.B redis-logical-db: \fI<logical database index>
|
||||
The logical database in Redis to use.
|
||||
These are databases in the same Redis instance sharing the same configuration
|
||||
and persisted in the same RDB/AOF file.
|
||||
If unsure about using this option, Redis documentation
|
||||
(https://redis.io/commands/select/) suggests not to use a single Redis instance
|
||||
for multiple unrelated applications.
|
||||
The default database in Redis is 0 while other logical databases need to be
|
||||
explicitly SELECT'ed upon connecting.
|
||||
This option defaults to 0.
|
||||
.SS DNSTAP Logging Options
|
||||
DNSTAP support, when compiled in by using \fB\-\-enable\-dnstap\fR, is enabled
|
||||
in the \fBdnstap:\fR section.
|
||||
|
@ -75,6 +75,7 @@ int dynlibmod_init(struct module_env* env, int id) {
|
||||
struct config_strlist* cfg_item = env->cfg->dynlib_file;
|
||||
struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
|
||||
__DYNMOD dynamic_library;
|
||||
int i;
|
||||
if (!de)
|
||||
{
|
||||
log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
|
||||
@ -84,7 +85,7 @@ int dynlibmod_init(struct module_env* env, int id) {
|
||||
env->modinfo[id] = (void*) de;
|
||||
|
||||
de->fname = NULL;
|
||||
for(int i = dynlib_mod_idx;
|
||||
for(i = dynlib_mod_idx;
|
||||
i != 0 && cfg_item != NULL;
|
||||
i--, cfg_item = cfg_item->next) {}
|
||||
|
||||
|
@ -156,6 +156,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
qstate->no_cache_store = 0;
|
||||
}
|
||||
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||
qstate->env->cfg->client_subnet_always_forward) ||
|
||||
ecs_is_whitelisted(sn_env->whitelist,
|
||||
@ -166,6 +167,14 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
* set. */
|
||||
if(!edns_opt_list_find(qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
/* if the client is not wanting an EDNS subnet option,
|
||||
* omit it and store that we omitted it but actually
|
||||
* are doing EDNS subnet to the server. */
|
||||
if(sq->ecs_server_out.subnet_source_mask == 0) {
|
||||
sq->subnet_sent_no_subnet = 1;
|
||||
sq->subnet_sent = 0;
|
||||
return 1;
|
||||
}
|
||||
subnet_ecs_opt_list_append(&sq->ecs_server_out,
|
||||
&qstate->edns_opts_back_out, qstate, region);
|
||||
}
|
||||
@ -515,7 +524,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
}
|
||||
|
||||
/* We have not asked for subnet data */
|
||||
if (!sq->subnet_sent) {
|
||||
if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) {
|
||||
if (s_in->subnet_validdata)
|
||||
verbose(VERB_QUERY, "subnetcache: received spurious data");
|
||||
if (sq->subnet_downstream) /* Copy back to client */
|
||||
@ -524,7 +533,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
}
|
||||
|
||||
/* subnet sent but nothing came back */
|
||||
if (!s_in->subnet_validdata) {
|
||||
if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) {
|
||||
/* The authority indicated no support for edns subnet. As a
|
||||
* consequence the answer ended up in the regular cache. It
|
||||
* is still useful to put it in the edns subnet cache for
|
||||
@ -540,6 +549,18 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/* Purposefully there was no sent subnet, and there is consequently
|
||||
* no subnet in the answer. If there was, use the subnet in the answer
|
||||
* anyway. But if there is not, treat it as a prefix 0 answer. */
|
||||
if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) {
|
||||
/* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */
|
||||
s_in->subnet_addr_fam = s_out->subnet_addr_fam;
|
||||
s_in->subnet_source_mask = 0;
|
||||
s_in->subnet_scope_mask = 0;
|
||||
memset(s_in->subnet_addr, 0, INET6_SIZE);
|
||||
s_in->subnet_validdata = 1;
|
||||
}
|
||||
|
||||
/* Being here means we have asked for and got a subnet specific
|
||||
* answer. Also, the answer from the authority is not yet cached
|
||||
* anywhere. */
|
||||
@ -556,6 +577,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
return module_restart_next;
|
||||
}
|
||||
|
||||
@ -676,6 +698,7 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
|
||||
} else if (!sq->track_max_scope &&
|
||||
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
|
||||
@ -737,6 +760,9 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
sq->ecs_server_in.subnet_scope_mask >
|
||||
sq->max_scope))
|
||||
sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
|
||||
} else if(sq->subnet_sent_no_subnet) {
|
||||
/* The answer can be stored as scope 0, not in global cache. */
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -85,6 +85,13 @@ struct subnet_qstate {
|
||||
struct ecs_data ecs_server_out;
|
||||
int subnet_downstream;
|
||||
int subnet_sent;
|
||||
/**
|
||||
* If there was no subnet sent because the client used source prefix
|
||||
* length 0 for omitting the information. Then the answer is cached
|
||||
* like subnet was a /0 scope. Like the subnet_sent flag, but when
|
||||
* the EDNS subnet option is omitted because the client asked.
|
||||
*/
|
||||
int subnet_sent_no_subnet;
|
||||
/** keep track of longest received scope, set after receiving CNAME for
|
||||
* incoming QNAME. */
|
||||
int track_max_scope;
|
||||
|
@ -207,28 +207,6 @@ size_t priv_get_mem(struct iter_priv* priv)
|
||||
return sizeof(*priv) + regional_get_mem(priv->region);
|
||||
}
|
||||
|
||||
/** remove RR from msgparse RRset, return true if rrset is entirely bad */
|
||||
static int
|
||||
remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset,
|
||||
struct rr_parse* prev, struct rr_parse** rr, struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) {
|
||||
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_pkt_copy(pkt, buf, rrset->dname);
|
||||
log_name_addr(VERB_QUERY, str, buf, addr, addrlen);
|
||||
}
|
||||
if(prev)
|
||||
prev->next = (*rr)->next;
|
||||
else rrset->rr_first = (*rr)->next;
|
||||
if(rrset->rr_last == *rr)
|
||||
rrset->rr_last = prev;
|
||||
rrset->rr_count --;
|
||||
rrset->size -= (*rr)->size;
|
||||
/* rr struct still exists, but is unlinked, so that in the for loop
|
||||
* the rr->next works fine to continue. */
|
||||
return rrset->rr_count == 0;
|
||||
}
|
||||
|
||||
int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
struct rrset_parse* rrset)
|
||||
{
|
||||
@ -261,7 +239,7 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
INET_SIZE);
|
||||
memmove(&addr, &sa, len);
|
||||
if(priv_lookup_addr(priv, &addr, len)) {
|
||||
if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, len))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
@ -284,7 +262,7 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
INET6_SIZE);
|
||||
memmove(&addr, &sa, len);
|
||||
if(priv_lookup_addr(priv, &addr, len)) {
|
||||
if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, len))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "config.h"
|
||||
#include "iterator/iter_resptype.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
@ -105,7 +106,8 @@ response_type_from_cache(struct dns_msg* msg,
|
||||
|
||||
enum response_type
|
||||
response_type_from_server(int rdset,
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp)
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
|
||||
int* empty_nodata_found)
|
||||
{
|
||||
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
|
||||
struct ub_packed_rrset_key* s;
|
||||
@ -284,13 +286,22 @@ response_type_from_server(int rdset,
|
||||
|
||||
/* If we've gotten this far, this is NOERROR/NODATA (which could
|
||||
* be an entirely empty message) */
|
||||
/* but ignore entirely empty messages, noerror/nodata has a soa
|
||||
* negative ttl value in the authority section, this makes it try
|
||||
* again at another authority. And turns it from a 5 second empty
|
||||
* message into a 5 second servfail response. */
|
||||
/* For entirely empty messages, try again, at first, then accept
|
||||
* it it happens more. A regular noerror/nodata response has a soa
|
||||
* negative ttl value in the authority section. This makes it try
|
||||
* again at another authority. And decides between storing a 5 second
|
||||
* empty message or a 5 second servfail response. */
|
||||
if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 &&
|
||||
msg->rep->ar_numrrsets == 0)
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
msg->rep->ar_numrrsets == 0) {
|
||||
if(empty_nodata_found) {
|
||||
/* detect as throwaway at first, but accept later. */
|
||||
(*empty_nodata_found)++;
|
||||
if(*empty_nodata_found < EMPTY_NODATA_RETRY_COUNT)
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
/* check if recursive answer; saying it has empty cache */
|
||||
if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
|
@ -119,9 +119,11 @@ enum response_type response_type_from_cache(struct dns_msg* msg,
|
||||
* @param request: the request that generated the response.
|
||||
* @param dp: The delegation point that was being queried
|
||||
* when the response was returned.
|
||||
* @param empty_nodata_found: flag to keep track of empty nodata detection.
|
||||
* @return the response type (CNAME or ANSWER).
|
||||
*/
|
||||
enum response_type response_type_from_server(int rdset,
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp);
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
|
||||
int* empty_nodata_found);
|
||||
|
||||
#endif /* ITERATOR_ITER_RESPTYPE_H */
|
||||
|
@ -716,6 +716,56 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Remove individual RRs, if the length is wrong. Returns true if the RRset
|
||||
* has been removed. */
|
||||
static int
|
||||
scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct rrset_parse* prev, struct rrset_parse** rrset, int* added_ede,
|
||||
struct module_qstate* qstate)
|
||||
{
|
||||
struct rr_parse* rr, *rr_prev = NULL;
|
||||
for(rr = (*rrset)->rr_first; rr; rr = rr->next) {
|
||||
|
||||
/* Sanity check for length of records
|
||||
* An A record should be 6 bytes only
|
||||
* (2 bytes for length and 4 for IPv4 addr)*/
|
||||
if((*rrset)->type == LDNS_RR_TYPE_A && rr->size != 6 ) {
|
||||
if(!*added_ede) {
|
||||
*added_ede = 1;
|
||||
errinf_ede(qstate, "sanitize: records of inappropriate length have been removed.",
|
||||
LDNS_EDE_OTHER);
|
||||
}
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing type A RR of inappropriate length:",
|
||||
pkt, *rrset, rr_prev, rr, NULL, 0)) {
|
||||
remove_rrset("sanitize: removing type A RRset of inappropriate length:",
|
||||
pkt, msg, prev, rrset);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Sanity check for length of records
|
||||
* An AAAA record should be 18 bytes only
|
||||
* (2 bytes for length and 16 for IPv6 addr)*/
|
||||
if((*rrset)->type == LDNS_RR_TYPE_AAAA && rr->size != 18 ) {
|
||||
if(!*added_ede) {
|
||||
*added_ede = 1;
|
||||
errinf_ede(qstate, "sanitize: records of inappropriate length have been removed.",
|
||||
LDNS_EDE_OTHER);
|
||||
}
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing type AAAA RR of inappropriate length:",
|
||||
pkt, *rrset, rr_prev, rr, NULL, 0)) {
|
||||
remove_rrset("sanitize: removing type AAAA RRset of inappropriate length:",
|
||||
pkt, msg, prev, rrset);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
rr_prev = rr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a response event, remove suspect RRsets from the response.
|
||||
* "Suspect" rrsets are potentially poison. Note that this routine expects
|
||||
@ -728,15 +778,17 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
|
||||
* @param zonename: name of server zone.
|
||||
* @param env: module environment with config and cache.
|
||||
* @param ie: iterator environment with private address data.
|
||||
* @param qstate: for setting errinf for EDE error messages.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
static int
|
||||
scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
||||
struct iter_env* ie)
|
||||
struct iter_env* ie, struct module_qstate* qstate)
|
||||
{
|
||||
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
||||
do not trust the normalized additional-A-AAAA any more */
|
||||
int added_rrlen_ede = 0;
|
||||
struct rrset_parse* rrset, *prev;
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
@ -781,6 +833,14 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset) {
|
||||
|
||||
/* Sanity check for length of records */
|
||||
if(rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA) {
|
||||
if(scrub_sanitize_rr_length(pkt, msg, prev, &rrset,
|
||||
&added_rrlen_ede, qstate))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* remove private addresses */
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
@ -854,7 +914,8 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
int
|
||||
scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* region,
|
||||
struct module_env* env, struct iter_env* ie)
|
||||
struct module_env* env, struct module_qstate* qstate,
|
||||
struct iter_env* ie)
|
||||
{
|
||||
/* basic sanity checks */
|
||||
log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS,
|
||||
@ -886,7 +947,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
if(!scrub_normalize(pkt, msg, qinfo, region, env))
|
||||
return 0;
|
||||
/* delete all out-of-zone information */
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie))
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ struct query_info;
|
||||
struct regional;
|
||||
struct module_env;
|
||||
struct iter_env;
|
||||
struct module_qstate;
|
||||
|
||||
/**
|
||||
* Cleanup the passed dns message.
|
||||
@ -59,11 +60,13 @@ struct iter_env;
|
||||
* Used to determine out of bailiwick information.
|
||||
* @param regional: where to allocate (new) parts of the message.
|
||||
* @param env: module environment with config settings and cache.
|
||||
* @param qstate: for setting errinf for EDE error messages.
|
||||
* @param ie: iterator module environment data.
|
||||
* @return: false if the message is total waste. true if scrubbed with success.
|
||||
*/
|
||||
int scrub_message(struct sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* regional,
|
||||
struct module_env* env, struct iter_env* ie);
|
||||
struct module_env* env, struct module_qstate* qstate,
|
||||
struct iter_env* ie);
|
||||
|
||||
#endif /* ITERATOR_ITER_SCRUB_H */
|
||||
|
@ -2940,7 +2940,7 @@ static int
|
||||
processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct iter_env* ie, int id)
|
||||
{
|
||||
int dnsseclame = 0, origtypecname = 0;
|
||||
int dnsseclame = 0, origtypecname = 0, orig_empty_nodata_found;
|
||||
enum response_type type;
|
||||
|
||||
iq->num_current_queries--;
|
||||
@ -2960,12 +2960,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
iq->timeout_count = 0;
|
||||
orig_empty_nodata_found = iq->empty_nodata_found;
|
||||
type = response_type_from_server(
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qinfo_out, iq->dp);
|
||||
iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found);
|
||||
iq->chase_to_rd = 0;
|
||||
/* remove TC flag, if this is erroneously set by TCP upstream */
|
||||
iq->response->rep->flags &= ~BIT_TC;
|
||||
if(orig_empty_nodata_found != iq->empty_nodata_found &&
|
||||
iq->empty_nodata_found < EMPTY_NODATA_RETRY_COUNT) {
|
||||
/* try to search at another server */
|
||||
if(qstate->reply) {
|
||||
struct delegpt_addr* a = delegpt_find_addr(
|
||||
iq->dp, &qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen);
|
||||
/* make selection disprefer it */
|
||||
if(a) a->lame = 1;
|
||||
}
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
|
||||
!iq->auth_zone_response) {
|
||||
/* When forwarding (RD bit is set), we handle referrals
|
||||
@ -3501,7 +3514,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
|
||||
iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */
|
||||
type = response_type_from_server(
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qchase, iq->dp);
|
||||
iq->response, &iq->qchase, iq->dp, NULL);
|
||||
if(type == RESPONSE_TYPE_ANSWER) {
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = iq->response;
|
||||
@ -3874,6 +3887,23 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* explicitly set the EDE string to NULL */
|
||||
iq->response->rep->reason_bogus_str = NULL;
|
||||
if((qstate->env->cfg->val_log_level >= 2 ||
|
||||
qstate->env->cfg->log_servfail) && qstate->errinf &&
|
||||
!qstate->env->cfg->val_log_squelch) {
|
||||
char* err_str = errinf_to_str_misc(qstate);
|
||||
if(err_str) {
|
||||
size_t err_str_len = strlen(err_str);
|
||||
verbose(VERB_ALGO, "iterator EDE: %s", err_str);
|
||||
/* allocate space and store the error
|
||||
* string */
|
||||
iq->response->rep->reason_bogus_str = regional_alloc(
|
||||
qstate->region,
|
||||
sizeof(char) * (err_str_len+1));
|
||||
memcpy(iq->response->rep->reason_bogus_str,
|
||||
err_str, err_str_len+1);
|
||||
}
|
||||
free(err_str);
|
||||
}
|
||||
|
||||
/* we have finished processing this query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
@ -4098,7 +4128,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* normalize and sanitize: easy to delete items from linked lists */
|
||||
if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name,
|
||||
qstate->env->scratch, qstate->env, ie)) {
|
||||
qstate->env->scratch, qstate->env, qstate, ie)) {
|
||||
/* if 0x20 enabled, start fallback, but we have no message */
|
||||
if(event == module_event_capsfail && !iq->caps_fallback) {
|
||||
iq->caps_fallback = 1;
|
||||
|
@ -101,6 +101,8 @@ extern int BLACKLIST_PENALTY;
|
||||
* Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
|
||||
* fast server, this causes server exploration as a side benefit. msec. */
|
||||
#define RTT_BAND 400
|
||||
/** Number of retries for empty nodata packets before it is accepted. */
|
||||
#define EMPTY_NODATA_RETRY_COUNT 2
|
||||
|
||||
/**
|
||||
* Global state for the iterator.
|
||||
@ -415,6 +417,11 @@ struct iter_qstate {
|
||||
*/
|
||||
int refetch_glue;
|
||||
|
||||
/**
|
||||
* This flag detects that a completely empty nodata was received,
|
||||
* already so that it is accepted later. */
|
||||
int empty_nodata_found;
|
||||
|
||||
/** list of pending queries to authoritative servers. */
|
||||
struct outbound_list outlist;
|
||||
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "util/random.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/proxy_protocol.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/net_help.h"
|
||||
@ -168,6 +169,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
#ifdef HAVE_SSL
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||
if(!w->sslctx) {
|
||||
@ -175,6 +177,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
#endif
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
@ -263,6 +266,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
w->env->kill_sub = &mesh_state_delete;
|
||||
w->env->detect_cycle = &mesh_detect_cycle;
|
||||
comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
|
||||
pp_init(&sldns_write_uint16, &sldns_write_uint32);
|
||||
return w;
|
||||
}
|
||||
|
||||
|
@ -863,6 +863,9 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
%inline %{
|
||||
//SWIG will see the ub_ctx as a class
|
||||
struct ub_ctx {
|
||||
/* Dummy member, so the struct is not empty, MSVC complains about
|
||||
* that. */
|
||||
int dummy;
|
||||
};
|
||||
%}
|
||||
|
||||
|
@ -33,7 +33,12 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
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):
|
||||
@ -55,12 +60,15 @@ def setTTL(qstate, ttl):
|
||||
|
||||
def dataHex(data, prefix=""):
|
||||
res = ""
|
||||
for i in range(0, (len(data)+15)/16):
|
||||
for i in range(0, int((len(data)+15)/16)):
|
||||
res += "%s0x%02X | " % (prefix, i*16)
|
||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||
if type(data[0]) == type(1):
|
||||
d = map(lambda x:int(x), data[i*16:i*16+17])
|
||||
else:
|
||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||
for ch in d:
|
||||
res += "%02X " % ch
|
||||
for i in range(0,17-len(d)):
|
||||
for i in range(0,17-len(data[i*16:i*16+17])):
|
||||
res += " "
|
||||
res += "| "
|
||||
for ch in d:
|
||||
@ -72,31 +80,31 @@ def dataHex(data, prefix=""):
|
||||
return res
|
||||
|
||||
def printReturnMsg(qstate):
|
||||
print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
|
||||
print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
|
||||
print("Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl))
|
||||
print(" qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str)
|
||||
if (qstate.return_msg.rep):
|
||||
print "RRSets:",qstate.return_msg.rep.rrset_count
|
||||
print("RRSets:",qstate.return_msg.rep.rrset_count)
|
||||
prevkey = None
|
||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||
r = qstate.return_msg.rep.rrsets[i]
|
||||
rk = r.rk
|
||||
print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
|
||||
print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
|
||||
print(i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags)
|
||||
print("type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class))
|
||||
|
||||
d = r.entry.data
|
||||
print " RRDatas:",d.count+d.rrsig_count
|
||||
print(" RRDatas:",d.count+d.rrsig_count)
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
print " ",j,":","TTL=",d.rr_ttl[j],"RR data:"
|
||||
print dataHex(d.rr_data[j]," ")
|
||||
print(" ",j,":","TTL=",d.rr_ttl[j],"RR data:")
|
||||
print(dataHex(d.rr_data[j]," "))
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
||||
#print "pythonmod: per query data", qdata
|
||||
#print("pythonmod: per query data", qdata)
|
||||
|
||||
print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list,
|
||||
print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
|
||||
print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
|
||||
print
|
||||
print("Query:", qstate.qinfo.qname, qstate.qinfo.qname_list, qstate.qinfo.qname_str)
|
||||
print("Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype)
|
||||
print("Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass)
|
||||
print("")
|
||||
|
||||
# TEST:
|
||||
# > dig @127.0.0.1 www.seznam.cz A
|
||||
@ -118,7 +126,7 @@ def operate(id, event, qstate, qdata):
|
||||
invalidateQueryInCache(qstate, qstate.return_msg.qinfo)
|
||||
|
||||
if (qstate.return_msg.rep.authoritative):
|
||||
print "X"*300
|
||||
print("X"*300)
|
||||
|
||||
setTTL(qstate, 10) #do cache nastavime TTL na 10
|
||||
if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
|
||||
|
@ -2475,6 +2475,7 @@ az_find_ce(struct auth_zone* z, struct query_info* qinfo,
|
||||
struct auth_rrset** rrset)
|
||||
{
|
||||
struct auth_data* n = node;
|
||||
struct auth_rrset* lookrrset;
|
||||
*ce = NULL;
|
||||
*rrset = NULL;
|
||||
if(!node_exact) {
|
||||
@ -2497,21 +2498,23 @@ az_find_ce(struct auth_zone* z, struct query_info* qinfo,
|
||||
/* see if the current candidate has issues */
|
||||
/* not zone apex and has type NS */
|
||||
if(n->namelen != z->namelen &&
|
||||
(*rrset=az_domain_rrset(n, LDNS_RR_TYPE_NS)) &&
|
||||
(lookrrset=az_domain_rrset(n, LDNS_RR_TYPE_NS)) &&
|
||||
/* delegate here, but DS at exact the dp has notype */
|
||||
(qinfo->qtype != LDNS_RR_TYPE_DS ||
|
||||
n->namelen != qinfo->qname_len)) {
|
||||
/* referral */
|
||||
/* this is ce and the lowernode is nonexisting */
|
||||
*ce = n;
|
||||
return 0;
|
||||
*rrset = lookrrset;
|
||||
node_exact = 0;
|
||||
}
|
||||
/* not equal to qname and has type DNAME */
|
||||
if(n->namelen != qinfo->qname_len &&
|
||||
(*rrset=az_domain_rrset(n, LDNS_RR_TYPE_DNAME))) {
|
||||
(lookrrset=az_domain_rrset(n, LDNS_RR_TYPE_DNAME))) {
|
||||
/* this is ce and the lowernode is nonexisting */
|
||||
*ce = n;
|
||||
return 0;
|
||||
*rrset = lookrrset;
|
||||
node_exact = 0;
|
||||
}
|
||||
|
||||
if(*ce == NULL && !domain_has_only_nsec3(n)) {
|
||||
|
@ -1391,8 +1391,15 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (sock_queue_timeout && !set_recvtimestamp(s)) {
|
||||
log_warn("socket timestamping is not available");
|
||||
if(udp_port_type == listen_type_udp && sock_queue_timeout)
|
||||
udp_port_type = listen_type_udpancil;
|
||||
if (sock_queue_timeout) {
|
||||
if(!set_recvtimestamp(s)) {
|
||||
log_warn("socket timestamping is not available");
|
||||
} else {
|
||||
if(udp_port_type == listen_type_udp)
|
||||
udp_port_type = listen_type_udpancil;
|
||||
}
|
||||
}
|
||||
if(!port_insert(list, s, udp_port_type, is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
@ -1583,9 +1590,13 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
}
|
||||
} else if(ports->ftype == listen_type_udpancil ||
|
||||
ports->ftype == listen_type_udpancil_dnscrypt) {
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
|
||||
cp = comm_point_create_udp_ancil(base, ports->fd,
|
||||
front->udp_buff, ports->pp2_enabled, cb,
|
||||
cb_arg, ports->socket);
|
||||
#else
|
||||
log_warn("This system does not support UDP ancilliary data.");
|
||||
#endif
|
||||
}
|
||||
if(!cp) {
|
||||
log_err("can't create commpoint");
|
||||
|
@ -1224,11 +1224,12 @@ static inline int
|
||||
mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m)
|
||||
{
|
||||
struct respip_action_info const* respip_info = m->s.respip_action_info;
|
||||
return respip_info == NULL
|
||||
return (respip_info == NULL
|
||||
? 0
|
||||
: (respip_info->rpz_used
|
||||
&& !respip_info->rpz_disabled
|
||||
&& respip_info->action == respip_truncate);
|
||||
&& respip_info->action == respip_truncate))
|
||||
|| m->s.tcp_required;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -550,7 +550,6 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
|
||||
log_assert(&key_p.reuse != (struct reuse_tcp*)result);
|
||||
log_assert(&key_p != ((struct reuse_tcp*)result)->pending);
|
||||
}
|
||||
/* not found, return null */
|
||||
|
||||
/* It is possible that we search for something before the first element
|
||||
* in the tree. Replace a null pointer with the first element.
|
||||
@ -560,6 +559,7 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
|
||||
result = rbtree_first(&outnet->tcp_reuse);
|
||||
}
|
||||
|
||||
/* not found, return null */
|
||||
if(!result || result == RBTREE_NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -2162,7 +2162,7 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
* honored before the query gets sent. */
|
||||
ms->respip_action_info->action = respip_truncate;
|
||||
ms->tcp_required = 1;
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
@ -2217,7 +2217,7 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
* honored before the query gets sent. */
|
||||
ms->respip_action_info->action = respip_truncate;
|
||||
ms->tcp_required = 1;
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
@ -2428,7 +2428,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
* honored before the query gets sent. */
|
||||
ms->respip_action_info->action = respip_truncate;
|
||||
ms->tcp_required = 1;
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
|
@ -192,6 +192,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
|
||||
{ 6, "DHU" },
|
||||
{ 7, "N3U" },
|
||||
{ 8, "edns-client-subnet" },
|
||||
{ 10, "COOKIE" },
|
||||
{ 11, "edns-tcp-keepalive"},
|
||||
{ 12, "Padding" },
|
||||
{ 15, "EDE"},
|
||||
@ -199,6 +200,38 @@ static sldns_lookup_table sldns_edns_options_data[] = {
|
||||
};
|
||||
sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
|
||||
|
||||
/* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */
|
||||
static sldns_lookup_table sldns_edns_ede_codes_data[] = {
|
||||
{ LDNS_EDE_NONE, "None" },
|
||||
{ LDNS_EDE_OTHER, "Other Error" },
|
||||
{ LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" },
|
||||
{ LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" },
|
||||
{ LDNS_EDE_STALE_ANSWER, "Stale Answer" },
|
||||
{ LDNS_EDE_FORGED_ANSWER, "Forged Answer" },
|
||||
{ LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" },
|
||||
{ LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" },
|
||||
{ LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" },
|
||||
{ LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" },
|
||||
{ LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" },
|
||||
{ LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" },
|
||||
{ LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" },
|
||||
{ LDNS_EDE_NSEC_MISSING, "NSEC Missing" },
|
||||
{ LDNS_EDE_CACHED_ERROR, "Cached Error" },
|
||||
{ LDNS_EDE_NOT_READY, "Not Ready" },
|
||||
{ LDNS_EDE_BLOCKED, "Blocked" },
|
||||
{ LDNS_EDE_CENSORED, "Censored" },
|
||||
{ LDNS_EDE_FILTERED, "Filtered" },
|
||||
{ LDNS_EDE_PROHIBITED, "Prohibited" },
|
||||
{ LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" },
|
||||
{ LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" },
|
||||
{ LDNS_EDE_NOT_SUPPORTED, "Not Supported" },
|
||||
{ LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" },
|
||||
{ LDNS_EDE_NETWORK_ERROR, "Network Error" },
|
||||
{ LDNS_EDE_INVALID_DATA, "Invalid Data" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data;
|
||||
|
||||
static sldns_lookup_table sldns_tsig_errors_data[] = {
|
||||
{ LDNS_TSIG_ERROR_NOERROR, "NOERROR" },
|
||||
{ LDNS_RCODE_FORMERR, "FORMERR" },
|
||||
@ -2234,6 +2267,52 @@ static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl,
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_edns_ede_print(char** s, size_t* sl,
|
||||
uint8_t* data, size_t len)
|
||||
{
|
||||
uint16_t ede_code;
|
||||
int w = 0;
|
||||
sldns_lookup_table *lt;
|
||||
size_t i;
|
||||
int printable;
|
||||
|
||||
if(len < 2) {
|
||||
w += sldns_str_print(s, sl, "malformed ede ");
|
||||
w += print_hex_buf(s, sl, data, len);
|
||||
return w;
|
||||
}
|
||||
|
||||
ede_code = sldns_read_uint16(data);
|
||||
lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code);
|
||||
if(lt && lt->name)
|
||||
w += sldns_str_print(s, sl, "%s", lt->name);
|
||||
else w += sldns_str_print(s, sl, "%d", (int)ede_code);
|
||||
|
||||
if(len == 2)
|
||||
return w;
|
||||
|
||||
w += sldns_str_print(s, sl, " ");
|
||||
|
||||
/* If it looks like text, show it as text. */
|
||||
printable=1;
|
||||
for(i=2; i<len; i++) {
|
||||
if(isprint((unsigned char)data[i]) || data[i] == '\t')
|
||||
continue;
|
||||
printable = 0;
|
||||
break;
|
||||
}
|
||||
if(printable) {
|
||||
w += sldns_str_print(s, sl, "\"");
|
||||
for(i=2; i<len; i++) {
|
||||
w += str_char_print(s, sl, data[i]);
|
||||
}
|
||||
w += sldns_str_print(s, sl, "\"");
|
||||
} else {
|
||||
w += print_hex_buf(s, sl, data+2, len-2);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_edns_option_print(char** s, size_t* sl,
|
||||
uint16_t option_code, uint8_t* optdata, size_t optlen)
|
||||
{
|
||||
@ -2268,6 +2347,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl,
|
||||
case LDNS_EDNS_PADDING:
|
||||
w += print_hex_buf(s, sl, optdata, optlen);
|
||||
break;
|
||||
case LDNS_EDNS_EDE:
|
||||
w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen);
|
||||
break;
|
||||
default:
|
||||
/* unknown option code */
|
||||
w += print_hex_buf(s, sl, optdata, optlen);
|
||||
|
@ -36,6 +36,8 @@ extern struct sldns_struct_lookup_table* sldns_opcodes;
|
||||
extern struct sldns_struct_lookup_table* sldns_edns_flags;
|
||||
/** EDNS option codes */
|
||||
extern struct sldns_struct_lookup_table* sldns_edns_options;
|
||||
/** EDNS EDE codes */
|
||||
extern struct sldns_struct_lookup_table* sldns_edns_ede_codes;
|
||||
/** error string from wireparse */
|
||||
extern struct sldns_struct_lookup_table* sldns_wireparse_errors;
|
||||
/** tsig errors are the rcodes with extra (higher) values */
|
||||
@ -1020,6 +1022,17 @@ int sldns_wire2str_edns_n3u_print(char** str, size_t* str_len,
|
||||
int sldns_wire2str_edns_subnet_print(char** str, size_t* str_len,
|
||||
uint8_t* option_data, size_t option_len);
|
||||
|
||||
/**
|
||||
* Print EDNS EDE option data to string. User buffers, moves string pointers.
|
||||
* @param str: string buffer.
|
||||
* @param str_len: length of string buffer.
|
||||
* @param option_data: buffer with EDNS option code data.
|
||||
* @param option_len: length of the data for this option.
|
||||
* @return number of characters (except null) needed to print.
|
||||
*/
|
||||
int sldns_wire2str_edns_ede_print(char** str, size_t* str_len,
|
||||
uint8_t* option_data, size_t option_len);
|
||||
|
||||
/**
|
||||
* Print an EDNS option as OPT: VALUE. User buffers, moves string pointers.
|
||||
* @param str: string buffer.
|
||||
|
@ -61,6 +61,17 @@ Specify the server to send the queries to. If not specified localhost (127.0.0.1
|
||||
.B \-d \fIsecs
|
||||
Delay after the connection before sending query. This tests the timeout
|
||||
on the other side, eg. if shorter the connection is closed.
|
||||
.TP
|
||||
.B \-p \fIclient
|
||||
Use proxy protocol to send the query. Specify the ipaddr@portnr of the client
|
||||
to include in PROXYv2.
|
||||
.TP
|
||||
.B IXFR=serial
|
||||
Pass the type of the query as IXFR=N to send an IXFR query with serial N.
|
||||
.TP
|
||||
.B NOTIFY[=serial]
|
||||
Pass the type of the query as NOTIFY[=N] to send a notify packet. The serial N
|
||||
of the new zone can be included.
|
||||
.SH "EXAMPLES"
|
||||
.LP
|
||||
Some examples of use.
|
||||
|
@ -79,6 +79,8 @@ static void usage(char* argv[])
|
||||
printf("-d secs delay after connection before sending query\n");
|
||||
printf("-s use ssl\n");
|
||||
printf("-h this help text\n");
|
||||
printf("IXFR=N for the type, sends ixfr query with serial N.\n");
|
||||
printf("NOTIFY[=N] for the type, sends notify. Can set new zone serial N.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -115,6 +117,29 @@ open_svr(const char* svr, int udp, struct sockaddr_storage* addr,
|
||||
return fd;
|
||||
}
|
||||
|
||||
/** Append a SOA record with serial number */
|
||||
static void
|
||||
write_soa_serial_to_buf(sldns_buffer* buf, struct query_info* qinfo,
|
||||
uint32_t serial)
|
||||
{
|
||||
sldns_buffer_set_position(buf, sldns_buffer_limit(buf));
|
||||
sldns_buffer_set_limit(buf, sldns_buffer_capacity(buf));
|
||||
/* Write compressed reference to the query */
|
||||
sldns_buffer_write_u16(buf, PTR_CREATE(LDNS_HEADER_SIZE));
|
||||
sldns_buffer_write_u16(buf, LDNS_RR_TYPE_SOA);
|
||||
sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
sldns_buffer_write_u32(buf, 3600); /* TTL */
|
||||
sldns_buffer_write_u16(buf, 1+1+4*5); /* rdatalen */
|
||||
sldns_buffer_write_u8(buf, 0); /* primary "." */
|
||||
sldns_buffer_write_u8(buf, 0); /* email "." */
|
||||
sldns_buffer_write_u32(buf, serial); /* serial */
|
||||
sldns_buffer_write_u32(buf, 0); /* refresh */
|
||||
sldns_buffer_write_u32(buf, 0); /* retry */
|
||||
sldns_buffer_write_u32(buf, 0); /* expire */
|
||||
sldns_buffer_write_u32(buf, 0); /* minimum */
|
||||
sldns_buffer_flip(buf);
|
||||
}
|
||||
|
||||
/** write a query over the TCP fd */
|
||||
static void
|
||||
write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
|
||||
@ -123,6 +148,8 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
|
||||
{
|
||||
struct query_info qinfo;
|
||||
size_t proxy_buf_limit = sldns_buffer_limit(proxy_buf);
|
||||
int have_serial = 0, is_notify = 0;
|
||||
uint32_t serial = 0;
|
||||
/* qname */
|
||||
qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len);
|
||||
if(!qinfo.qname) {
|
||||
@ -130,12 +157,27 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* qtype and qclass */
|
||||
qinfo.qtype = sldns_get_rr_type_by_name(strtype);
|
||||
if(qinfo.qtype == 0 && strcmp(strtype, "TYPE0") != 0) {
|
||||
printf("cannot parse query type: '%s'\n", strtype);
|
||||
exit(1);
|
||||
/* qtype */
|
||||
if(strncasecmp(strtype, "IXFR=", 5) == 0) {
|
||||
serial = (uint32_t)atoi(strtype+5);
|
||||
have_serial = 1;
|
||||
qinfo.qtype = LDNS_RR_TYPE_IXFR;
|
||||
} else if(strcasecmp(strtype, "NOTIFY") == 0) {
|
||||
is_notify = 1;
|
||||
qinfo.qtype = LDNS_RR_TYPE_SOA;
|
||||
} else if(strncasecmp(strtype, "NOTIFY=", 7) == 0) {
|
||||
serial = (uint32_t)atoi(strtype+7);
|
||||
have_serial = 1;
|
||||
is_notify = 1;
|
||||
qinfo.qtype = LDNS_RR_TYPE_SOA;
|
||||
} else {
|
||||
qinfo.qtype = sldns_get_rr_type_by_name(strtype);
|
||||
if(qinfo.qtype == 0 && strcmp(strtype, "TYPE0") != 0) {
|
||||
printf("cannot parse query type: '%s'\n", strtype);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/* qclass */
|
||||
qinfo.qclass = sldns_get_rr_class_by_name(strclass);
|
||||
if(qinfo.qclass == 0 && strcmp(strclass, "CLASS0") != 0) {
|
||||
printf("cannot parse query class: '%s'\n", strclass);
|
||||
@ -150,6 +192,21 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
|
||||
sldns_buffer_write_u16_at(buf, 0, id);
|
||||
sldns_buffer_write_u16_at(buf, 2, BIT_RD);
|
||||
|
||||
if(have_serial && qinfo.qtype == LDNS_RR_TYPE_IXFR) {
|
||||
/* Attach serial to SOA record in the authority section. */
|
||||
write_soa_serial_to_buf(buf, &qinfo, serial);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(buf), 1);
|
||||
}
|
||||
if(is_notify) {
|
||||
LDNS_OPCODE_SET(sldns_buffer_begin(buf), LDNS_PACKET_NOTIFY);
|
||||
LDNS_RD_CLR(sldns_buffer_begin(buf));
|
||||
LDNS_AA_SET(sldns_buffer_begin(buf));
|
||||
if(have_serial) {
|
||||
write_soa_serial_to_buf(buf, &qinfo, serial);
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(buf), 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(1) {
|
||||
/* add EDNS DO */
|
||||
struct edns_data edns;
|
||||
@ -361,6 +418,7 @@ static int parse_pp2_client(const char* pp2_client, int udp,
|
||||
sldns_buffer* proxy_buf)
|
||||
{
|
||||
struct sockaddr_storage pp2_addr;
|
||||
size_t bytes_written;
|
||||
socklen_t pp2_addrlen = 0;
|
||||
memset(&pp2_addr, 0, sizeof(pp2_addr));
|
||||
if(*pp2_client == 0) return 0;
|
||||
@ -369,7 +427,9 @@ static int parse_pp2_client(const char* pp2_client, int udp,
|
||||
exit(1);
|
||||
}
|
||||
sldns_buffer_clear(proxy_buf);
|
||||
pp2_write_to_buf(proxy_buf, &pp2_addr, !udp);
|
||||
bytes_written = pp2_write_to_buf(sldns_buffer_begin(proxy_buf),
|
||||
sldns_buffer_remaining(proxy_buf), &pp2_addr, !udp);
|
||||
sldns_buffer_set_position(proxy_buf, bytes_written);
|
||||
sldns_buffer_flip(proxy_buf);
|
||||
return 1;
|
||||
}
|
||||
@ -541,6 +601,8 @@ int main(int argc, char** argv)
|
||||
break;
|
||||
case 'p':
|
||||
pp2_client = optarg;
|
||||
pp_init(&sldns_write_uint16,
|
||||
&sldns_write_uint32);
|
||||
break;
|
||||
case 'a':
|
||||
onarrival = 1;
|
||||
|
@ -76,10 +76,18 @@ static const char* zone_example_com =
|
||||
"out.example.com. 3600 IN CNAME www.example.com.\n"
|
||||
"plan.example.com. 3600 IN CNAME nonexist.example.com.\n"
|
||||
"redir.example.com. 3600 IN DNAME redir.example.org.\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
"obscured.redir2.example.com. 3600 IN A 10.0.0.12\n"
|
||||
"under2.redir2.example.com. 3600 IN DNAME redir3.example.net.\n"
|
||||
"doubleobscured.under2.redir2.example.com. 3600 IN A 10.0.0.13\n"
|
||||
"sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
"sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
"ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
"obscured.sub2.example.com. 3600 IN A 10.0.0.10\n"
|
||||
"under.sub2.example.com. 3600 IN NS ns.under.sub2.example.com.\n"
|
||||
"doubleobscured.under.sub2.example.com. 3600 IN A 10.0.0.11\n"
|
||||
"*.wild.example.com. 3600 IN A 10.0.0.8\n"
|
||||
"*.wild2.example.com. 3600 IN CNAME www.example.com.\n"
|
||||
"*.wild3.example.com. 3600 IN A 10.0.0.8\n"
|
||||
@ -281,6 +289,54 @@ static struct q_ans example_com_queries[] = {
|
||||
"foo.abc.redir.example.com. 0 IN CNAME foo.abc.redir.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "redir2.example.com. DNAME", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";answer section\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "abc.redir2.example.com. A", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";answer section\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
"abc.redir2.example.com. 0 IN CNAME abc.redir2.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "obscured.redir2.example.com. A", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";answer section\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
"obscured.redir2.example.com. 0 IN CNAME obscured.redir2.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "under2.redir2.example.com. A", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";answer section\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
"under2.redir2.example.com. 0 IN CNAME under2.redir2.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "doubleobscured.under2.redir2.example.com. A", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";answer section\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
"doubleobscured.under2.redir2.example.com. 0 IN CNAME doubleobscured.under2.redir2.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "foo.doubleobscured.under2.redir2.example.com. A", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";answer section\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
"foo.doubleobscured.under2.redir2.example.com. 0 IN CNAME foo.doubleobscured.under2.redir2.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "foo.under2.redir2.example.com. A", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";answer section\n"
|
||||
"redir2.example.com. 3600 IN DNAME redir2.example.org.\n"
|
||||
"foo.under2.redir2.example.com. 0 IN CNAME foo.under2.redir2.example.org.\n"
|
||||
},
|
||||
|
||||
{ "example.com", "sub.example.com. NS", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
@ -357,6 +413,78 @@ static struct q_ans example_com_queries[] = {
|
||||
"ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
|
||||
},
|
||||
|
||||
{ "example.com", "sub2.example.com. A", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "sub2.example.com. NS", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "obscured.sub2.example.com. A", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "abc.obscured.sub2.example.com. A", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "under.sub2.example.com. A", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "under.sub2.example.com. NS", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "abc.under.sub2.example.com. A", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "doubleobscured.under.sub2.example.com. A", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "abc.doubleobscured.under.sub2.example.com. A", "",
|
||||
";flags QR rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
"sub2.example.com. 3600 IN NS ns1.sub.example.com.\n"
|
||||
";additional section\n"
|
||||
"ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
|
||||
},
|
||||
|
||||
{ "example.com", "wild.example.com. A", "",
|
||||
";flags QR AA rcode NOERROR\n"
|
||||
";authority section\n"
|
||||
|
48
testdata/dns64_lookup.rpl
vendored
48
testdata/dns64_lookup.rpl
vendored
@ -140,33 +140,6 @@ SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
broken.example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
; NO AAAA present
|
||||
SECTION AUTHORITY
|
||||
example.com. IN SOA a. b. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
broken.example.com. IN A
|
||||
SECTION ANSWER
|
||||
broken.example.com. IN A 5.6.7.8
|
||||
broken.example.com. IN A \# 3 030405
|
||||
SECTION AUTHORITY
|
||||
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
|
||||
@ -284,25 +257,4 @@ SECTION AUTHORITY
|
||||
7.6.5.in-addr.arpa. IN NS ns.example.com.
|
||||
ENTRY_END
|
||||
|
||||
; synthesize from broken, malformed A records
|
||||
STEP 80 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
broken.example.com. IN AAAA
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 90 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
broken.example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.com. IN SOA a. b. 1 2 3 4 5
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
|
50
testdata/iter_ignore_empty.rpl
vendored
50
testdata/iter_ignore_empty.rpl
vendored
@ -78,6 +78,18 @@ example2.com. IN NS ns2.example2.com.
|
||||
SECTION ADDITIONAL
|
||||
ns2.example2.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.foo.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.foo.com. IN A 1.2.3.5
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com.
|
||||
@ -172,6 +184,27 @@ www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
ENTRY_END
|
||||
|
||||
; foo.com
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
www.foo.com. IN A
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
ns.foo.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
;foo.com. IN SOA ns2.foo.com root.foo.com 4 14400 3600 604800 3600
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
@ -195,4 +228,21 @@ ENTRY_END
|
||||
; wait for pending nameserver lookups.
|
||||
STEP 20 TRAFFIC
|
||||
|
||||
; Test that a nodata stays a nodata.
|
||||
STEP 30 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.foo.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 40 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.foo.com. IN A
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
|
298
testdata/iter_scrub_rr_length.rpl
vendored
Normal file
298
testdata/iter_scrub_rr_length.rpl
vendored
Normal file
@ -0,0 +1,298 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
qname-minimisation: "no"
|
||||
minimal-responses: no
|
||||
rrset-roundrobin: no
|
||||
ede: yes
|
||||
log-servfail: yes
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test scrub of RRs of inappropriate length
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 200
|
||||
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 200
|
||||
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 qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
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 200
|
||||
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
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
www.example.com. IN A \# 3 030405
|
||||
SECTION AUTHORITY
|
||||
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
|
||||
www.example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
www.example.com. IN AAAA 2001:db8::1234
|
||||
www.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F
|
||||
SECTION AUTHORITY
|
||||
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
|
||||
broken1.example.com. IN A
|
||||
SECTION ANSWER
|
||||
broken1.example.com. IN A \# 3 030405
|
||||
broken1.example.com. IN A \# 3 030406
|
||||
SECTION AUTHORITY
|
||||
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
|
||||
broken1.example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
broken1.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F
|
||||
broken1.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E30
|
||||
broken1.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E31
|
||||
SECTION AUTHORITY
|
||||
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
|
||||
broken2.example.com. IN A
|
||||
SECTION ANSWER
|
||||
broken2.example.com. IN A 1.2.3.4
|
||||
broken2.example.com. IN A \# 3 030405
|
||||
broken2.example.com. IN A 1.2.3.5
|
||||
broken2.example.com. IN A \# 3 030406
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A \# 3 030407
|
||||
ns.example.com. IN A 1.2.3.6
|
||||
ns.example.com. IN A \# 3 030408
|
||||
ns.example.com. IN A \# 3 030409
|
||||
ns.example.com. IN A 1.2.3.7
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
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. 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
|
||||
|
||||
STEP 20 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN AAAA
|
||||
ENTRY_END
|
||||
|
||||
STEP 30 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
www.example.com. IN AAAA 2001:db8::1234
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
STEP 40 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
broken1.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 50 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
broken1.example.com. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
STEP 60 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
broken1.example.com. IN AAAA
|
||||
ENTRY_END
|
||||
|
||||
STEP 70 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
broken1.example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
STEP 80 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
broken2.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 90 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
broken2.example.com. IN A
|
||||
SECTION ANSWER
|
||||
broken2.example.com. IN A 1.2.3.4
|
||||
broken2.example.com. IN A 1.2.3.5
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.6
|
||||
ns.example.com. IN A 1.2.3.7
|
||||
ENTRY_END
|
||||
|
||||
STEP 100 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD CD DO
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 110 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ede=0
|
||||
REPLY QR RD CD RA DO 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.6
|
||||
ns.example.com. IN A 1.2.3.7
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
34
testdata/root_zonemd.tdir/root_zonemd.conf
vendored
Normal file
34
testdata/root_zonemd.tdir/root_zonemd.conf
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
server:
|
||||
verbosity: 7
|
||||
# num-threads: 1
|
||||
interface: 127.0.0.1
|
||||
port: @PORT@
|
||||
use-syslog: no
|
||||
directory: ""
|
||||
pidfile: "unbound.pid"
|
||||
chroot: ""
|
||||
username: ""
|
||||
do-not-query-localhost: no
|
||||
# for the test, so that DNSSEC verification works.
|
||||
#val-override-date: 20230929090000
|
||||
trust-anchor: ". DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D"
|
||||
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: @CONTROL_PATH@/controlpipe.@CONTROL_PID@
|
||||
control-use-cert: no
|
||||
|
||||
# for the test, an upstream server in the test setup.
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 127.0.0.1@@TOPORT@
|
||||
|
||||
# hyperlocal root zone
|
||||
auth-zone:
|
||||
name: "."
|
||||
fallback-enabled: yes
|
||||
for-downstream: no
|
||||
for-upstream: yes
|
||||
zonefile: "root.zone"
|
||||
zonemd-check: yes
|
||||
zonemd-reject-absence: yes
|
16
testdata/root_zonemd.tdir/root_zonemd.dsc
vendored
Normal file
16
testdata/root_zonemd.tdir/root_zonemd.dsc
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
BaseName: root_zonemd
|
||||
Version: 1.0
|
||||
Description: ZONEMD check for root zone
|
||||
CreationDate: Fri 29 Sep 09:00:00 CEST 2023
|
||||
Maintainer: dr. W.C.A. Wijngaards
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends:
|
||||
Help:
|
||||
Pre: root_zonemd.pre
|
||||
Post: root_zonemd.post
|
||||
Test: root_zonemd.test
|
||||
AuxFiles:
|
||||
Passed:
|
||||
Failure:
|
14
testdata/root_zonemd.tdir/root_zonemd.post
vendored
Normal file
14
testdata/root_zonemd.tdir/root_zonemd.post
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
# #-- root_zonemd.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
|
||||
echo "> cat logfiles"
|
||||
cat fwd.log
|
||||
cat unbound.log
|
||||
kill_pid $FWD_PID
|
||||
kill_pid $UNBOUND_PID
|
||||
rm -f $CONTROL_PATH/controlpipe.$CONTROL_PID
|
50
testdata/root_zonemd.tdir/root_zonemd.pre
vendored
Normal file
50
testdata/root_zonemd.tdir/root_zonemd.pre
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
# #-- root_zonemd.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
|
||||
|
||||
# attempt to download the root zone
|
||||
from=k.root-servers.net
|
||||
dig @$from . AXFR > root.txt
|
||||
if test $? -ne 0; then
|
||||
echo "could not fetch root zone"
|
||||
skip_test "could not fetch root zone"
|
||||
fi
|
||||
grep " SOA " root.txt | head -1 > root.soa
|
||||
cat root.soa >> root.zone
|
||||
grep -v " SOA " root.txt >> root.zone
|
||||
echo "fetched root.zone"
|
||||
ls -l root.zone
|
||||
cat root.soa
|
||||
|
||||
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 root_zonemd.testns >fwd.log 2>&1 &
|
||||
FWD_PID=$!
|
||||
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
|
||||
|
||||
# make config file
|
||||
CONTROL_PATH=/tmp
|
||||
CONTROL_PID=$$
|
||||
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's?@CONTROL_PATH\@?'$CONTROL_PATH'?' -e 's/@CONTROL_PID@/'$CONTROL_PID'/' < root_zonemd.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
|
||||
echo "CONTROL_PATH=$CONTROL_PATH" >> .tpkg.var.test
|
||||
echo "CONTROL_PID=$CONTROL_PID" >> .tpkg.var.test
|
||||
|
||||
cat .tpkg.var.test
|
||||
wait_ldns_testns_up fwd.log
|
||||
wait_unbound_up unbound.log
|
||||
|
51
testdata/root_zonemd.tdir/root_zonemd.test
vendored
Normal file
51
testdata/root_zonemd.tdir/root_zonemd.test
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
# #-- root_zonemd.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 . SOA | tee outfile
|
||||
echo "> check answer"
|
||||
if grep root-servers outfile | grep "nstld.verisign-grs.com"; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "Not OK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "> unbound-control status"
|
||||
$PRE/unbound-control -c ub.conf status
|
||||
if test $? -ne 0; then
|
||||
echo "wrong exit value."
|
||||
exit 1
|
||||
else
|
||||
echo "exit value: OK"
|
||||
fi
|
||||
|
||||
# This is the output when an unsupported algorithm is used.
|
||||
if grep "auth zone . ZONEMD unsupported algorithm" unbound.log; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "ZONEMD verification not OK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "> unbound-control auth_zone_reload ."
|
||||
$PRE/unbound-control -c ub.conf auth_zone_reload . 2>&1 | tee outfile
|
||||
if test $? -ne 0; then
|
||||
echo "wrong exit value."
|
||||
exit 1
|
||||
fi
|
||||
# The output of the reload can be checked.
|
||||
#echo "> check unbound-control output"
|
||||
#if grep "example.com: ZONEMD verification successful" outfile; then
|
||||
#echo "OK"
|
||||
#else
|
||||
#echo "Not OK"
|
||||
#exit 1
|
||||
#fi
|
||||
|
||||
exit 0
|
9
testdata/root_zonemd.tdir/root_zonemd.testns
vendored
Normal file
9
testdata/root_zonemd.tdir/root_zonemd.testns
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# reply to everything
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR SERVFAIL
|
||||
SECTION QUESTION
|
||||
example.com. IN SOA
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
81
testdata/rpz_nsdname.rpl
vendored
81
testdata/rpz_nsdname.rpl
vendored
@ -225,6 +225,36 @@ ENTRY_END
|
||||
|
||||
RANGE_END
|
||||
|
||||
; dd. ------------------------------------------------------------------------
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 8.8.3.8
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
dd. IN NS
|
||||
SECTION ANSWER
|
||||
dd. IN NS ns1.dd.
|
||||
SECTION ADDITIONAL
|
||||
ns1.dd. IN A 8.8.3.8
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
gotham.dd. IN A
|
||||
SECTION AUTHORITY
|
||||
gotham.dd. IN NS ns1.gotham.dd.
|
||||
SECTION ADDITIONAL
|
||||
ns1.gotham.dd. IN A 192.0.3.1
|
||||
ENTRY_END
|
||||
|
||||
RANGE_END
|
||||
|
||||
; ff. ------------------------------------------------------------------------
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 8.8.6.8
|
||||
@ -303,6 +333,22 @@ ENTRY_END
|
||||
|
||||
RANGE_END
|
||||
|
||||
; ns1.gotham.dd. -------------------------------------------------------------
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.0.3.1
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
gotham.dd. IN A
|
||||
SECTION ANSWER
|
||||
gotham.dd. IN A 192.0.3.2
|
||||
ENTRY_END
|
||||
|
||||
RANGE_END
|
||||
|
||||
; ns1.gotham.ff. -------------------------------------------------------------
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.0.5.1
|
||||
@ -387,4 +433,39 @@ SECTION ANSWER
|
||||
gotham.ff. IN A 127.0.0.1
|
||||
ENTRY_END
|
||||
|
||||
STEP 40 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
gotham.dd. IN A
|
||||
ENTRY_END
|
||||
|
||||
; should come back truncated because TCP is required.
|
||||
STEP 41 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA TC NOERROR
|
||||
SECTION QUESTION
|
||||
gotham.dd. IN A
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
||||
|
||||
STEP 42 QUERY
|
||||
ENTRY_BEGIN
|
||||
MATCH TCP
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
gotham.dd. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 43 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all TCP
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
gotham.dd. IN A
|
||||
SECTION ANSWER
|
||||
gotham.dd. IN A 192.0.3.2
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
|
155
testdata/subnet_prezero.crpl
vendored
Normal file
155
testdata/subnet_prezero.crpl
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
; subnet unit test
|
||||
server:
|
||||
trust-anchor-signaling: no
|
||||
send-client-subnet: 1.2.3.4
|
||||
send-client-subnet: 1.2.3.5
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
module-config: "subnetcache validator iterator"
|
||||
qname-minimisation: no
|
||||
minimal-responses: no
|
||||
|
||||
stub-zone:
|
||||
name: "example.com"
|
||||
stub-addr: 1.2.3.4
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test subnetcache source prefix zero from client.
|
||||
; In RFC7871 section-7.1.2 (para. 2).
|
||||
; It says that the recursor must send no EDNS subnet or its own address
|
||||
; in the EDNS subnet to the upstream server. And use that answer for the
|
||||
; source prefix length zero query. That type of query is for privacy.
|
||||
; The authority server is then going to use the resolver's IP, if any, to
|
||||
; tailor the answer to the query source address.
|
||||
|
||||
; ns.example.com
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.4
|
||||
|
||||
; reply with 0.0.0.0/0 in reply
|
||||
; For the test the answers for 0.0.0.0/0 queries are SERVFAIL, the normal
|
||||
; answers are NOERROR.
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR AA DO SERVFAIL
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN CNAME star.c10r.example.com.
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
00 08 00 04 ; OPCODE=subnet, optlen
|
||||
00 01 00 00 ; ip4, scope 0, source 0
|
||||
; 0.0.0.0/0
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
; reply without subnet
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA DO NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN CNAME star.c10r.example.com.
|
||||
ENTRY_END
|
||||
|
||||
; delegation answer for c10r.example.com, with subnet /0
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain ednsdata
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR DO SERVFAIL
|
||||
SECTION QUESTION
|
||||
c10r.example.com. IN NS
|
||||
SECTION AUTHORITY
|
||||
c10r.example.com. IN NS ns.c10r.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.c10r.example.com. IN A 1.2.3.5
|
||||
HEX_EDNSDATA_BEGIN
|
||||
00 08 00 04 ; OPCODE=subnet, optlen
|
||||
00 01 00 00 ; ip4, scope 0, source 0
|
||||
; 0.0.0.0/0
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
; delegation answer for c10r.example.com, without subnet
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR DO NOERROR
|
||||
SECTION QUESTION
|
||||
c10r.example.com. IN NS
|
||||
SECTION AUTHORITY
|
||||
c10r.example.com. IN NS ns.c10r.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.c10r.example.com. IN A 1.2.3.5
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.c10r.example.com
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.5
|
||||
|
||||
; reply with 0.0.0.0/0 in reply
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR AA DO SERVFAIL
|
||||
SECTION QUESTION
|
||||
star.c10r.example.com. IN A
|
||||
SECTION ANSWER
|
||||
star.c10r.example.com. IN A 1.2.3.6
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
00 08 00 04 ; OPCODE=subnet, optlen
|
||||
00 01 00 00 ; ip4, scope 0, source 0
|
||||
; 0.0.0.0/0
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
; reply without subnet
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA DO NOERROR
|
||||
SECTION QUESTION
|
||||
star.c10r.example.com. IN A
|
||||
SECTION ANSWER
|
||||
star.c10r.example.com. IN A 1.2.3.6
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ask for www.example.com
|
||||
; server answers with CNAME to a delegation, that then
|
||||
; returns a /24 answer.
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
00 08 00 04 ; OPCODE=subnet, optlen
|
||||
00 01 00 00 ; ip4, scope 0, source 0
|
||||
; 0.0.0.0/0
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ednsdata
|
||||
REPLY QR RD RA DO NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN CNAME star.c10r.example.com.
|
||||
star.c10r.example.com. IN A 1.2.3.6
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
00 08 00 04 ; OPCODE=subnet, optlen
|
||||
00 01 00 00 ; ip4, scope 0, source 0
|
||||
; 0.0.0.0/0
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
SCENARIO_END
|
164
testdata/val_scrub_rr_length.rpl
vendored
Normal file
164
testdata/val_scrub_rr_length.rpl
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
; config options
|
||||
; The island of trust is at example.com
|
||||
server:
|
||||
trust-anchor: "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af"
|
||||
val-override-date: "20070916134226"
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
qname-minimisation: "no"
|
||||
trust-anchor-signaling: no
|
||||
minimal-responses: no
|
||||
rrset-roundrobin: no
|
||||
ede: yes
|
||||
log-servfail: yes
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test validator with scrub of RR for inappropriate length
|
||||
|
||||
; 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 qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
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.
|
||||
example.com. 3600 IN RRSIG NS 8 2 3600 20070926134150 20070829134150 55566 example.com. cHdLVCzujUQs6b67c1SmCX+/br4tgOg86Gj/R/x+PKUQmWHyeVwBSTlJuLOHbca3CQoyIQc+V2ilK6fjwjbY/dLk4uOlux8L+Zn7HsUXSOwJPIjsM3LuTa8CYDMvYhOP7KGR+vNpJVSsQ25pyDn6Rzsdl3E7DAf7uSkPV8VJwa8=
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 55566 example.com. PBwNifMNxTXlDorHX1neq1wUhWLmqk+PZ+PBZCI5BJAmakdgOXdLQiVqlKaErJyA/4uN+99fUf6/DqxwgxL8FIPdBkxMOTJaKrCFjEhL6qozTd3+DI6qFJPgTm1lrkpvb9W72MtK2vxAyT5I/bG2SWKdpzOaQXysbDb2hnxq3as=
|
||||
ENTRY_END
|
||||
|
||||
; response to DNSKEY priming query
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
example.com. IN DNSKEY 256 3 8 AwEAAdug/L739i0mgN2nuK/bhxu3wFn5Ud9nK2+XUmZQlPUEZUC5YZvm1rfMmEWTGBn87fFxEu/kjFZHJ55JLzqsbbpVHLbmKCTT2gYR2FV2WDKROGKuYbVkJIXdKAjJ0ONuK507NinYvlWXIoxHn22KAWOd9wKgSTNHBlmGkX+ts3hh ;{id = 55566 (zsk), size = 1024b}
|
||||
example.com. 3600 IN RRSIG DNSKEY 8 2 3600 20070926134150 20070829134150 55566 example.com. Ni7Q17l2dzKcAnHdU3Mycpdwo0I6qgGxRvBhBNI43xIUFHJpgKpbeMFxKvVTkbwHyMPMIuHmOaC82IBhOpGD10SExVh4erQhWS3Hvl+m4Cwl3WI9N+AW6CTB9yj+d4xzX3bHjjBt6MSk4bU8ABR7qIoAjgjY7zdtUDWQlaM+d18=
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 8 2 3600 20070926134150 20070829134150 55566 example.com. cHdLVCzujUQs6b67c1SmCX+/br4tgOg86Gj/R/x+PKUQmWHyeVwBSTlJuLOHbca3CQoyIQc+V2ilK6fjwjbY/dLk4uOlux8L+Zn7HsUXSOwJPIjsM3LuTa8CYDMvYhOP7KGR+vNpJVSsQ25pyDn6Rzsdl3E7DAf7uSkPV8VJwa8=
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 55566 example.com. PBwNifMNxTXlDorHX1neq1wUhWLmqk+PZ+PBZCI5BJAmakdgOXdLQiVqlKaErJyA/4uN+99fUf6/DqxwgxL8FIPdBkxMOTJaKrCFjEhL6qozTd3+DI6qFJPgTm1lrkpvb9W72MtK2vxAyT5I/bG2SWKdpzOaQXysbDb2hnxq3as=
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
ns.example.com. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 8 2 3600 20070926134150 20070829134150 55566 example.com. cHdLVCzujUQs6b67c1SmCX+/br4tgOg86Gj/R/x+PKUQmWHyeVwBSTlJuLOHbca3CQoyIQc+V2ilK6fjwjbY/dLk4uOlux8L+Zn7HsUXSOwJPIjsM3LuTa8CYDMvYhOP7KGR+vNpJVSsQ25pyDn6Rzsdl3E7DAf7uSkPV8VJwa8=
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 55566 example.com. PBwNifMNxTXlDorHX1neq1wUhWLmqk+PZ+PBZCI5BJAmakdgOXdLQiVqlKaErJyA/4uN+99fUf6/DqxwgxL8FIPdBkxMOTJaKrCFjEhL6qozTd3+DI6qFJPgTm1lrkpvb9W72MtK2vxAyT5I/bG2SWKdpzOaQXysbDb2hnxq3as=
|
||||
ENTRY_END
|
||||
|
||||
; response to query of interest
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
www.example.com. IN A \# 5 0102030405
|
||||
; RRSIG includes the malformed record.
|
||||
www.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 55566 example.com. W4WFu9B81uRvp3Dj8uLIscypznKWuLuKrZqVg1on5/45/3/xyjHvj3TjTL3gruWFXPiQpldvOstXLZ5eN3OpqILdkVey0eqVATujpHwIruY6GWztVx5WptmFfK6E6zzshZ3RmAARqq/czQ+IZli2A9xixdY2H0o1dSU6gohEjjE=
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 8 2 3600 20070926134150 20070829134150 55566 example.com. cHdLVCzujUQs6b67c1SmCX+/br4tgOg86Gj/R/x+PKUQmWHyeVwBSTlJuLOHbca3CQoyIQc+V2ilK6fjwjbY/dLk4uOlux8L+Zn7HsUXSOwJPIjsM3LuTa8CYDMvYhOP7KGR+vNpJVSsQ25pyDn6Rzsdl3E7DAf7uSkPV8VJwa8=
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 55566 example.com. PBwNifMNxTXlDorHX1neq1wUhWLmqk+PZ+PBZCI5BJAmakdgOXdLQiVqlKaErJyA/4uN+99fUf6/DqxwgxL8FIPdBkxMOTJaKrCFjEhL6qozTd3+DI6qFJPgTm1lrkpvb9W72MtK2vxAyT5I/bG2SWKdpzOaQXysbDb2hnxq3as=
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ede=0
|
||||
REPLY QR RD RA DO SERVFAIL
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
@ -390,6 +390,7 @@ config_create(void)
|
||||
cfg->redis_timeout = 100;
|
||||
cfg->redis_server_port = 6379;
|
||||
cfg->redis_expire_records = 0;
|
||||
cfg->redis_logical_db = 0;
|
||||
#endif /* USE_REDIS */
|
||||
#endif /* USE_CACHEDB */
|
||||
#ifdef USE_IPSET
|
||||
@ -1319,6 +1320,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
else O_STR(opt, "redis-server-password", redis_server_password)
|
||||
else O_DEC(opt, "redis-timeout", redis_timeout)
|
||||
else O_YNO(opt, "redis-expire-records", redis_expire_records)
|
||||
else O_DEC(opt, "redis-logical-db", redis_logical_db)
|
||||
#endif /* USE_REDIS */
|
||||
#endif /* USE_CACHEDB */
|
||||
#ifdef USE_IPSET
|
||||
|
@ -717,6 +717,8 @@ struct config_file {
|
||||
int redis_timeout;
|
||||
/** set timeout on redis records based on DNS response ttl */
|
||||
int redis_expire_records;
|
||||
/** set the redis logical database upon connection */
|
||||
int redis_logical_db;
|
||||
#endif
|
||||
#endif
|
||||
/** Downstream DNS Cookies */
|
||||
|
@ -565,6 +565,7 @@ redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }
|
||||
redis-server-password{COLON} { YDVAR(1, VAR_CACHEDB_REDISPASSWORD) }
|
||||
redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) }
|
||||
redis-expire-records{COLON} { YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) }
|
||||
redis-logical-db{COLON} { YDVAR(1, VAR_CACHEDB_REDISLOGICALDB) }
|
||||
ipset{COLON} { YDVAR(0, VAR_IPSET) }
|
||||
name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) }
|
||||
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
|
||||
|
@ -179,6 +179,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
|
||||
%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT
|
||||
%token VAR_CACHEDB_REDISEXPIRERECORDS VAR_CACHEDB_REDISPATH VAR_CACHEDB_REDISPASSWORD
|
||||
%token VAR_CACHEDB_REDISLOGICALDB
|
||||
%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM
|
||||
%token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
|
||||
%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
|
||||
@ -3716,7 +3717,8 @@ contents_cachedb: contents_cachedb content_cachedb
|
||||
| ;
|
||||
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
|
||||
redis_server_host | redis_server_port | redis_timeout |
|
||||
redis_expire_records | redis_server_path | redis_server_password
|
||||
redis_expire_records | redis_server_path | redis_server_password |
|
||||
redis_logical_db
|
||||
;
|
||||
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
|
||||
{
|
||||
@ -3819,6 +3821,21 @@ redis_expire_records: VAR_CACHEDB_REDISEXPIRERECORDS STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
redis_logical_db: VAR_CACHEDB_REDISLOGICALDB STRING_ARG
|
||||
{
|
||||
#if defined(USE_CACHEDB) && defined(USE_REDIS)
|
||||
int db;
|
||||
OUTYY(("P(redis_logical_db:%s)\n", $2));
|
||||
db = atoi($2);
|
||||
if((db == 0 && strcmp($2, "0") != 0) || db < 0)
|
||||
yyerror("valid redis logical database index expected");
|
||||
else cfg_parser->cfg->redis_logical_db = db;
|
||||
#else
|
||||
OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
|
||||
#endif
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_tcp_connection_limit:%s %s)\n", $2, $3));
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/rfc_1982.h"
|
||||
#include "util/edns.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/rrdef.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/parseutil.h"
|
||||
@ -1306,3 +1307,27 @@ log_edns_opt_list(enum verbosity_value level, const char* info_str,
|
||||
}
|
||||
}
|
||||
|
||||
/** remove RR from msgparse RRset, return true if rrset is entirely bad */
|
||||
int
|
||||
msgparse_rrset_remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset,
|
||||
struct rr_parse* prev, struct rr_parse* rr, struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) {
|
||||
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_pkt_copy(pkt, buf, rrset->dname);
|
||||
if(addr)
|
||||
log_name_addr(VERB_QUERY, str, buf, addr, addrlen);
|
||||
else log_nametypeclass(VERB_QUERY, str, buf,
|
||||
rrset->type, ntohs(rrset->rrset_class));
|
||||
}
|
||||
if(prev)
|
||||
prev->next = rr->next;
|
||||
else rrset->rr_first = rr->next;
|
||||
if(rrset->rr_last == rr)
|
||||
rrset->rr_last = prev;
|
||||
rrset->rr_count --;
|
||||
rrset->size -= rr->size;
|
||||
/* rr struct still exists, but is unlinked, so that in the for loop
|
||||
* the rr->next works fine to continue. */
|
||||
return rrset->rr_count == 0;
|
||||
}
|
||||
|
@ -371,4 +371,22 @@ void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset);
|
||||
void log_edns_opt_list(enum verbosity_value level, const char* info_str,
|
||||
struct edns_option* list);
|
||||
|
||||
/**
|
||||
* Remove RR from msgparse RRset.
|
||||
* @param str: this string is used for logging if verbose. If NULL, there is
|
||||
* no logging of the remove.
|
||||
* @param pkt: packet in buffer that is removed from. Used to log the name
|
||||
* of the item removed.
|
||||
* @param rrset: RRset that the RR is removed from.
|
||||
* @param prev: previous RR in list, or NULL.
|
||||
* @param rr: RR that is removed.
|
||||
* @param addr: address used for logging, if verbose, or NULL then it is not
|
||||
* used.
|
||||
* @param addrlen: length of addr, if that is not NULL.
|
||||
* @return true if rrset is entirely bad, it would then need to be removed.
|
||||
*/
|
||||
int msgparse_rrset_remove_rr(const char* str, struct sldns_buffer* pkt,
|
||||
struct rrset_parse* rrset, struct rr_parse* prev, struct rr_parse* rr,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
|
||||
#endif /* UTIL_DATA_MSGPARSE_H */
|
||||
|
@ -172,7 +172,9 @@ int
|
||||
fptr_whitelist_event(void (*fptr)(int, short, void *))
|
||||
{
|
||||
if(fptr == &comm_point_udp_callback) return 1;
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
|
||||
else if(fptr == &comm_point_udp_ancil_callback) return 1;
|
||||
#endif
|
||||
else if(fptr == &comm_point_tcp_accept_callback) return 1;
|
||||
else if(fptr == &comm_point_tcp_handle_callback) return 1;
|
||||
else if(fptr == &comm_timer_callback) return 1;
|
||||
|
@ -194,6 +194,24 @@ char* errinf_to_str_servfail(struct module_qstate* qstate)
|
||||
return p;
|
||||
}
|
||||
|
||||
char* errinf_to_str_misc(struct module_qstate* qstate)
|
||||
{
|
||||
char buf[20480];
|
||||
char* p = buf;
|
||||
size_t left = sizeof(buf);
|
||||
struct errinf_strlist* s;
|
||||
if(!qstate->errinf)
|
||||
snprintf(p, left, "misc failure");
|
||||
else for(s=qstate->errinf; s; s=s->next) {
|
||||
snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str);
|
||||
left -= strlen(p); p += strlen(p);
|
||||
}
|
||||
p = strdup(buf);
|
||||
if(!p)
|
||||
log_err("malloc failure in errinf_to_str");
|
||||
return p;
|
||||
}
|
||||
|
||||
void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
|
||||
{
|
||||
char buf[1024];
|
||||
|
@ -691,6 +691,8 @@ struct module_qstate {
|
||||
struct respip_action_info* respip_action_info;
|
||||
/** if the query is rpz passthru, no further rpz processing for it */
|
||||
int rpz_passthru;
|
||||
/* Flag tcp required. */
|
||||
int tcp_required;
|
||||
|
||||
/** whether the reply should be dropped */
|
||||
int is_drop;
|
||||
@ -842,6 +844,14 @@ sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate);
|
||||
*/
|
||||
char* errinf_to_str_servfail(struct module_qstate* qstate);
|
||||
|
||||
/**
|
||||
* Create error info in string. For misc failures that are not servfail.
|
||||
* @param qstate: query state.
|
||||
* @return string or NULL on malloc failure (already logged).
|
||||
* This string is malloced and has to be freed by caller.
|
||||
*/
|
||||
char* errinf_to_str_misc(struct module_qstate* qstate);
|
||||
|
||||
/**
|
||||
* Initialize the edns known options by allocating the required space.
|
||||
* @param env: the module environment.
|
||||
|
@ -809,6 +809,7 @@ addr_to_nat64(const struct sockaddr_storage* addr,
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
|
||||
struct sockaddr_in6 *sin6;
|
||||
uint8_t *v4_byte;
|
||||
int i;
|
||||
|
||||
/* This needs to be checked by the caller */
|
||||
log_assert(addr->ss_family == AF_INET);
|
||||
@ -826,7 +827,7 @@ addr_to_nat64(const struct sockaddr_storage* addr,
|
||||
nat64_prefixnet = nat64_prefixnet / 8;
|
||||
|
||||
v4_byte = (uint8_t *)&sin->sin_addr.s_addr;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
for(i = 0; i < 4; i++) {
|
||||
if(nat64_prefixnet == 8) {
|
||||
/* bits 64...71 are MBZ */
|
||||
sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0;
|
||||
|
171
util/netevent.c
171
util/netevent.c
@ -124,6 +124,8 @@
|
||||
|
||||
/** timeout in millisec to wait for write to unblock, packets dropped after.*/
|
||||
#define SEND_BLOCKED_WAIT_TIMEOUT 200
|
||||
/** max number of times to wait for write to unblock, packets dropped after.*/
|
||||
#define SEND_BLOCKED_MAX_RETRY 5
|
||||
|
||||
/** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */
|
||||
#ifndef SO_TIMESTAMP
|
||||
@ -410,9 +412,10 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||
WSAGetLastError() == WSAENOBUFS ||
|
||||
WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||
#endif
|
||||
int retries = 0;
|
||||
/* if we set the fd blocking, other threads suddenly
|
||||
* have a blocking fd that they operate on */
|
||||
while(sent == -1 && (
|
||||
while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && (
|
||||
#ifndef USE_WINSOCK
|
||||
errno == EAGAIN || errno == EINTR ||
|
||||
# ifdef EWOULDBLOCK
|
||||
@ -427,6 +430,13 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||
#endif
|
||||
)) {
|
||||
#if defined(HAVE_POLL) || defined(USE_WINSOCK)
|
||||
int send_nobufs = (
|
||||
#ifndef USE_WINSOCK
|
||||
errno == ENOBUFS
|
||||
#else
|
||||
WSAGetLastError() == WSAENOBUFS
|
||||
#endif
|
||||
);
|
||||
struct pollfd p;
|
||||
int pret;
|
||||
memset(&p, 0, sizeof(p));
|
||||
@ -465,8 +475,48 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||
log_err("poll udp out failed: %s",
|
||||
sock_strerror(errno));
|
||||
return 0;
|
||||
} else if((pret < 0 &&
|
||||
#ifndef USE_WINSOCK
|
||||
errno == ENOBUFS
|
||||
#else
|
||||
WSAGetLastError() == WSAENOBUFS
|
||||
#endif
|
||||
) || (send_nobufs && retries > 0)) {
|
||||
/* ENOBUFS, and poll returned without
|
||||
* a timeout. Or the retried send call
|
||||
* returned ENOBUFS. It is good to
|
||||
* wait a bit for the error to clear. */
|
||||
/* The timeout is 20*(2^(retries+1)),
|
||||
* it increases exponentially, starting
|
||||
* at 40 msec. After 5 tries, 1240 msec
|
||||
* have passed in total, when poll
|
||||
* returned the error, and 1200 msec
|
||||
* when send returned the errors. */
|
||||
#ifndef USE_WINSOCK
|
||||
pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
||||
#else
|
||||
pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
||||
#endif
|
||||
if(pret < 0 &&
|
||||
#ifndef USE_WINSOCK
|
||||
errno != EAGAIN && errno != EINTR &&
|
||||
# ifdef EWOULDBLOCK
|
||||
errno != EWOULDBLOCK &&
|
||||
# endif
|
||||
errno != ENOBUFS
|
||||
#else
|
||||
WSAGetLastError() != WSAEINPROGRESS &&
|
||||
WSAGetLastError() != WSAEINTR &&
|
||||
WSAGetLastError() != WSAENOBUFS &&
|
||||
WSAGetLastError() != WSAEWOULDBLOCK
|
||||
#endif
|
||||
) {
|
||||
log_err("poll udp out timer failed: %s",
|
||||
sock_strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */
|
||||
retries++;
|
||||
if (!is_connected) {
|
||||
sent = sendto(c->fd, (void*)sldns_buffer_begin(packet),
|
||||
sldns_buffer_remaining(packet), 0,
|
||||
@ -673,7 +723,8 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
|
||||
WSAGetLastError() == WSAENOBUFS ||
|
||||
WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||
#endif
|
||||
while(sent == -1 && (
|
||||
int retries = 0;
|
||||
while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && (
|
||||
#ifndef USE_WINSOCK
|
||||
errno == EAGAIN || errno == EINTR ||
|
||||
# ifdef EWOULDBLOCK
|
||||
@ -688,6 +739,13 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
|
||||
#endif
|
||||
)) {
|
||||
#if defined(HAVE_POLL) || defined(USE_WINSOCK)
|
||||
int send_nobufs = (
|
||||
#ifndef USE_WINSOCK
|
||||
errno == ENOBUFS
|
||||
#else
|
||||
WSAGetLastError() == WSAENOBUFS
|
||||
#endif
|
||||
);
|
||||
struct pollfd p;
|
||||
int pret;
|
||||
memset(&p, 0, sizeof(p));
|
||||
@ -726,8 +784,48 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
|
||||
log_err("poll udp out failed: %s",
|
||||
sock_strerror(errno));
|
||||
return 0;
|
||||
} else if((pret < 0 &&
|
||||
#ifndef USE_WINSOCK
|
||||
errno == ENOBUFS
|
||||
#else
|
||||
WSAGetLastError() == WSAENOBUFS
|
||||
#endif
|
||||
) || (send_nobufs && retries > 0)) {
|
||||
/* ENOBUFS, and poll returned without
|
||||
* a timeout. Or the retried send call
|
||||
* returned ENOBUFS. It is good to
|
||||
* wait a bit for the error to clear. */
|
||||
/* The timeout is 20*(2^(retries+1)),
|
||||
* it increases exponentially, starting
|
||||
* at 40 msec. After 5 tries, 1240 msec
|
||||
* have passed in total, when poll
|
||||
* returned the error, and 1200 msec
|
||||
* when send returned the errors. */
|
||||
#ifndef USE_WINSOCK
|
||||
pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
||||
#else
|
||||
pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
||||
#endif
|
||||
if(pret < 0 &&
|
||||
#ifndef USE_WINSOCK
|
||||
errno != EAGAIN && errno != EINTR &&
|
||||
# ifdef EWOULDBLOCK
|
||||
errno != EWOULDBLOCK &&
|
||||
# endif
|
||||
errno != ENOBUFS
|
||||
#else
|
||||
WSAGetLastError() != WSAEINPROGRESS &&
|
||||
WSAGetLastError() != WSAEINTR &&
|
||||
WSAGetLastError() != WSAENOBUFS &&
|
||||
WSAGetLastError() != WSAEWOULDBLOCK
|
||||
#endif
|
||||
) {
|
||||
log_err("poll udp out timer failed: %s",
|
||||
sock_strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */
|
||||
retries++;
|
||||
sent = sendmsg(c->fd, &msg, 0);
|
||||
}
|
||||
}
|
||||
@ -802,15 +900,18 @@ static int udp_recv_needs_log(int err)
|
||||
static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
|
||||
int stream) {
|
||||
size_t size;
|
||||
struct pp2_header *header = pp2_read_header(buf);
|
||||
if(header == NULL) return 0;
|
||||
struct pp2_header *header;
|
||||
int err = pp2_read_header(sldns_buffer_begin(buf),
|
||||
sldns_buffer_remaining(buf));
|
||||
if(err) return 0;
|
||||
header = (struct pp2_header*)sldns_buffer_begin(buf);
|
||||
size = PP2_HEADER_SIZE + ntohs(header->len);
|
||||
if((header->ver_cmd & 0xF) == PP2_CMD_LOCAL) {
|
||||
/* A connection from the proxy itself.
|
||||
* No need to do anything with addresses. */
|
||||
goto done;
|
||||
}
|
||||
if(header->fam_prot == 0x00) {
|
||||
if(header->fam_prot == PP2_UNSPEC_UNSPEC) {
|
||||
/* Unspecified family and protocol. This could be used for
|
||||
* health checks by proxies.
|
||||
* No need to do anything with addresses. */
|
||||
@ -818,8 +919,8 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
|
||||
}
|
||||
/* Read the proxied address */
|
||||
switch(header->fam_prot) {
|
||||
case 0x11: /* AF_INET|STREAM */
|
||||
case 0x12: /* AF_INET|DGRAM */
|
||||
case PP2_INET_STREAM:
|
||||
case PP2_INET_DGRAM:
|
||||
{
|
||||
struct sockaddr_in* addr =
|
||||
(struct sockaddr_in*)&rep->client_addr;
|
||||
@ -830,8 +931,8 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
|
||||
}
|
||||
/* Ignore the destination address; it should be us. */
|
||||
break;
|
||||
case 0x21: /* AF_INET6|STREAM */
|
||||
case 0x22: /* AF_INET6|DGRAM */
|
||||
case PP2_INET6_STREAM:
|
||||
case PP2_INET6_DGRAM:
|
||||
{
|
||||
struct sockaddr_in6* addr =
|
||||
(struct sockaddr_in6*)&rep->client_addr;
|
||||
@ -844,6 +945,10 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
|
||||
}
|
||||
/* Ignore the destination address; it should be us. */
|
||||
break;
|
||||
default:
|
||||
log_err("proxy_protocol: unsupported family and "
|
||||
"protocol 0x%x", (int)header->fam_prot);
|
||||
return 0;
|
||||
}
|
||||
rep->is_proxied = 1;
|
||||
done:
|
||||
@ -858,10 +963,10 @@ done:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
|
||||
void
|
||||
comm_point_udp_ancil_callback(int fd, short event, void* arg)
|
||||
{
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
|
||||
struct comm_reply rep;
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
@ -980,14 +1085,8 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
|
||||
if(!rep.c || rep.c->fd == -1) /* commpoint closed */
|
||||
break;
|
||||
}
|
||||
#else
|
||||
(void)fd;
|
||||
(void)event;
|
||||
(void)arg;
|
||||
fatal_exit("recvmsg: No support for IPV6_PKTINFO; IP_PKTINFO or IP_RECVDSTADDR. "
|
||||
"Please disable interface-automatic");
|
||||
#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */
|
||||
}
|
||||
#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */
|
||||
|
||||
void
|
||||
comm_point_udp_callback(int fd, short event, void* arg)
|
||||
@ -3495,19 +3594,25 @@ ssl_handle_read(struct comm_point* c)
|
||||
return 0;
|
||||
}
|
||||
c->tcp_byte_count += r;
|
||||
sldns_buffer_skip(c->buffer, r);
|
||||
if(c->tcp_byte_count != current_read_size) return 1;
|
||||
c->pp2_header_state = pp2_header_init;
|
||||
}
|
||||
}
|
||||
if(c->pp2_header_state == pp2_header_init) {
|
||||
header = pp2_read_header(c->buffer);
|
||||
if(!header) {
|
||||
int err;
|
||||
err = pp2_read_header(
|
||||
sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_limit(c->buffer));
|
||||
if(err) {
|
||||
log_err("proxy_protocol: could not parse "
|
||||
"PROXYv2 header");
|
||||
"PROXYv2 header (%s)",
|
||||
pp_lookup_error(err));
|
||||
return 0;
|
||||
}
|
||||
header = (struct pp2_header*)sldns_buffer_begin(c->buffer);
|
||||
want_read_size = ntohs(header->len);
|
||||
if(sldns_buffer_remaining(c->buffer) <
|
||||
if(sldns_buffer_limit(c->buffer) <
|
||||
PP2_HEADER_SIZE + want_read_size) {
|
||||
log_err_addr("proxy_protocol: not enough "
|
||||
"buffer size to read PROXYv2 header", "",
|
||||
@ -3556,6 +3661,7 @@ ssl_handle_read(struct comm_point* c)
|
||||
return 0;
|
||||
}
|
||||
c->tcp_byte_count += r;
|
||||
sldns_buffer_skip(c->buffer, r);
|
||||
if(c->tcp_byte_count != current_read_size) return 1;
|
||||
c->pp2_header_state = pp2_header_done;
|
||||
}
|
||||
@ -3566,6 +3672,7 @@ ssl_handle_read(struct comm_point* c)
|
||||
c->repinfo.remote_addrlen);
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_flip(c->buffer);
|
||||
if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) {
|
||||
log_err_addr("proxy_protocol: could not consume "
|
||||
"PROXYv2 header", "", &c->repinfo.remote_addr,
|
||||
@ -3887,19 +3994,25 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
|
||||
goto recv_error_initial;
|
||||
}
|
||||
c->tcp_byte_count += r;
|
||||
sldns_buffer_skip(c->buffer, r);
|
||||
if(c->tcp_byte_count != current_read_size) return 1;
|
||||
c->pp2_header_state = pp2_header_init;
|
||||
}
|
||||
}
|
||||
if(c->pp2_header_state == pp2_header_init) {
|
||||
header = pp2_read_header(c->buffer);
|
||||
if(!header) {
|
||||
int err;
|
||||
err = pp2_read_header(
|
||||
sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_limit(c->buffer));
|
||||
if(err) {
|
||||
log_err("proxy_protocol: could not parse "
|
||||
"PROXYv2 header");
|
||||
"PROXYv2 header (%s)",
|
||||
pp_lookup_error(err));
|
||||
return 0;
|
||||
}
|
||||
header = (struct pp2_header*)sldns_buffer_begin(c->buffer);
|
||||
want_read_size = ntohs(header->len);
|
||||
if(sldns_buffer_remaining(c->buffer) <
|
||||
if(sldns_buffer_limit(c->buffer) <
|
||||
PP2_HEADER_SIZE + want_read_size) {
|
||||
log_err_addr("proxy_protocol: not enough "
|
||||
"buffer size to read PROXYv2 header", "",
|
||||
@ -3926,6 +4039,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
|
||||
goto recv_error;
|
||||
}
|
||||
c->tcp_byte_count += r;
|
||||
sldns_buffer_skip(c->buffer, r);
|
||||
if(c->tcp_byte_count != current_read_size) return 1;
|
||||
c->pp2_header_state = pp2_header_done;
|
||||
}
|
||||
@ -3936,6 +4050,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
|
||||
c->repinfo.remote_addrlen);
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_flip(c->buffer);
|
||||
if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) {
|
||||
log_err_addr("proxy_protocol: could not consume "
|
||||
"PROXYv2 header", "", &c->repinfo.remote_addr,
|
||||
@ -5634,11 +5749,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
|
||||
evbits = UB_EV_READ | UB_EV_PERSIST;
|
||||
/* ub_event stuff */
|
||||
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
|
||||
#ifdef USE_WINSOCK
|
||||
comm_point_udp_callback, c);
|
||||
#else
|
||||
comm_point_udp_ancil_callback, c);
|
||||
#endif
|
||||
if(c->ev->ev == NULL) {
|
||||
log_err("could not baseset udp event");
|
||||
comm_point_delete(c);
|
||||
@ -5653,6 +5764,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
|
||||
return c;
|
||||
}
|
||||
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
|
||||
struct comm_point*
|
||||
comm_point_create_udp_ancil(struct comm_base *base, int fd,
|
||||
sldns_buffer* buffer, int pp2_enabled,
|
||||
@ -5715,6 +5827,7 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
|
||||
c->event_added = 1;
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct comm_point*
|
||||
comm_point_create_doq(struct comm_base *base, int fd, sldns_buffer* buffer,
|
||||
|
@ -38,102 +38,162 @@
|
||||
*
|
||||
* 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,
|
||||
/**
|
||||
* Internal struct initialized with function pointers for writing uint16 and
|
||||
* uint32.
|
||||
*/
|
||||
struct proxy_protocol_data {
|
||||
void (*write_uint16)(void* buf, uint16_t data);
|
||||
void (*write_uint32)(void* buf, uint32_t data);
|
||||
};
|
||||
struct proxy_protocol_data pp_data;
|
||||
|
||||
/**
|
||||
* Internal lookup table; could be further generic like sldns_lookup_table
|
||||
* for all the future generic stuff.
|
||||
*/
|
||||
struct proxy_protocol_lookup_table {
|
||||
int id;
|
||||
const char *text;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal parsing error text; could be exposed with pp_lookup_error.
|
||||
*/
|
||||
static struct proxy_protocol_lookup_table pp_parse_errors_data[] = {
|
||||
{ PP_PARSE_NOERROR, "no parse error" },
|
||||
{ PP_PARSE_SIZE, "not enough space for header" },
|
||||
{ PP_PARSE_WRONG_HEADERv2, "could not match PROXYv2 header" },
|
||||
{ PP_PARSE_UNKNOWN_CMD, "unknown command" },
|
||||
{ PP_PARSE_UNKNOWN_FAM_PROT, "unknown family and protocol" },
|
||||
};
|
||||
|
||||
void
|
||||
pp_init(void (*write_uint16)(void* buf, uint16_t data),
|
||||
void (*write_uint32)(void* buf, uint32_t data)) {
|
||||
pp_data.write_uint16 = write_uint16;
|
||||
pp_data.write_uint32 = write_uint32;
|
||||
}
|
||||
|
||||
const char*
|
||||
pp_lookup_error(enum pp_parse_errors error) {
|
||||
return pp_parse_errors_data[error].text;
|
||||
}
|
||||
|
||||
size_t
|
||||
pp2_write_to_buf(uint8_t* buf, size_t buflen,
|
||||
#ifdef INET6
|
||||
struct sockaddr_storage* src,
|
||||
#else
|
||||
struct sockaddr_in* src,
|
||||
#endif
|
||||
int stream)
|
||||
{
|
||||
int af;
|
||||
size_t expected_size;
|
||||
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)) {
|
||||
expected_size = PP2_HEADER_SIZE + (af==AF_INET?12:36);
|
||||
if(buflen < expected_size) {
|
||||
return 0;
|
||||
}
|
||||
/* sig */
|
||||
sldns_buffer_write(buf, PP2_SIG, PP2_SIG_LEN);
|
||||
memcpy(buf, PP2_SIG, PP2_SIG_LEN);
|
||||
buf += PP2_SIG_LEN;
|
||||
/* version and command */
|
||||
sldns_buffer_write_u8(buf, (PP2_VERSION << 4) | PP2_CMD_PROXY);
|
||||
if(af==AF_INET) {
|
||||
*buf = (PP2_VERSION << 4) | PP2_CMD_PROXY;
|
||||
buf++;
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
/* family and protocol */
|
||||
sldns_buffer_write_u8(buf,
|
||||
(PP2_AF_INET<<4) |
|
||||
(stream?PP2_PROT_STREAM:PP2_PROT_DGRAM));
|
||||
*buf = (PP2_AF_INET<<4) |
|
||||
(stream?PP2_PROT_STREAM:PP2_PROT_DGRAM);
|
||||
buf++;
|
||||
/* length */
|
||||
sldns_buffer_write_u16(buf, 12);
|
||||
(*pp_data.write_uint16)(buf, 12);
|
||||
buf += 2;
|
||||
/* src addr */
|
||||
sldns_buffer_write(buf,
|
||||
memcpy(buf,
|
||||
&((struct sockaddr_in*)src)->sin_addr.s_addr, 4);
|
||||
buf += 4;
|
||||
/* dst addr */
|
||||
sldns_buffer_write_u32(buf, 0);
|
||||
(*pp_data.write_uint32)(buf, 0);
|
||||
buf += 4;
|
||||
/* src port */
|
||||
sldns_buffer_write(buf,
|
||||
memcpy(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);
|
||||
buf += 2;
|
||||
/* 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);
|
||||
(*pp_data.write_uint16)(buf, 12);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
/* family and protocol */
|
||||
*buf = (PP2_AF_INET6<<4) |
|
||||
(stream?PP2_PROT_STREAM:PP2_PROT_DGRAM);
|
||||
buf++;
|
||||
/* length */
|
||||
(*pp_data.write_uint16)(buf, 36);
|
||||
buf += 2;
|
||||
/* src addr */
|
||||
memcpy(buf,
|
||||
&((struct sockaddr_in6*)src)->sin6_addr, 16);
|
||||
buf += 16;
|
||||
/* dst addr */
|
||||
memset(buf, 0, 16);
|
||||
buf += 16;
|
||||
/* src port */
|
||||
memcpy(buf, &((struct sockaddr_in6*)src)->sin6_port, 2);
|
||||
buf += 2;
|
||||
/* dst port */
|
||||
(*pp_data.write_uint16)(buf, 0);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
case AF_UNIX:
|
||||
/* fallthrough */
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return expected_size;
|
||||
}
|
||||
|
||||
struct pp2_header*
|
||||
pp2_read_header(struct sldns_buffer* buf)
|
||||
int
|
||||
pp2_read_header(uint8_t* buf, size_t buflen)
|
||||
{
|
||||
size_t size;
|
||||
struct pp2_header* header = (struct pp2_header*)sldns_buffer_begin(buf);
|
||||
struct pp2_header* header = (struct pp2_header*)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;
|
||||
if(buflen < PP2_HEADER_SIZE) {
|
||||
return PP_PARSE_SIZE;
|
||||
}
|
||||
/* 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;
|
||||
return PP_PARSE_WRONG_HEADERv2;
|
||||
}
|
||||
/* 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;
|
||||
if(buflen < size) {
|
||||
return PP_PARSE_SIZE;
|
||||
}
|
||||
/* 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;
|
||||
return PP_PARSE_UNKNOWN_CMD;
|
||||
}
|
||||
/* 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;
|
||||
if(header->fam_prot != PP2_UNSPEC_UNSPEC &&
|
||||
header->fam_prot != PP2_INET_STREAM &&
|
||||
header->fam_prot != PP2_INET_DGRAM &&
|
||||
header->fam_prot != PP2_INET6_STREAM &&
|
||||
header->fam_prot != PP2_INET6_DGRAM &&
|
||||
header->fam_prot != PP2_UNIX_STREAM &&
|
||||
header->fam_prot != PP2_UNIX_DGRAM) {
|
||||
return PP_PARSE_UNKNOWN_FAM_PROT;
|
||||
}
|
||||
/* We have a correct header */
|
||||
return header;
|
||||
return PP_PARSE_NOERROR;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@
|
||||
#ifndef PROXY_PROTOCOL_H
|
||||
#define PROXY_PROTOCOL_H
|
||||
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "config.h"
|
||||
|
||||
/** PROXYv2 minimum header size */
|
||||
#define PP2_HEADER_SIZE 16
|
||||
@ -51,11 +51,11 @@
|
||||
#define PP2_SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
|
||||
#define PP2_SIG_LEN 12
|
||||
|
||||
/** PROXYv2 version */
|
||||
/** PROXYv2 version (protocol value) */
|
||||
#define PP2_VERSION 0x2
|
||||
|
||||
/**
|
||||
* PROXYv2 command.
|
||||
* PROXYv2 command (protocol value).
|
||||
*/
|
||||
enum pp2_command {
|
||||
PP2_CMD_LOCAL = 0x0,
|
||||
@ -63,7 +63,7 @@ enum pp2_command {
|
||||
};
|
||||
|
||||
/**
|
||||
* PROXYv2 address family.
|
||||
* PROXYv2 address family (protocol value).
|
||||
*/
|
||||
enum pp2_af {
|
||||
PP2_AF_UNSPEC = 0x0,
|
||||
@ -73,7 +73,7 @@ enum pp2_af {
|
||||
};
|
||||
|
||||
/**
|
||||
* PROXYv2 protocol.
|
||||
* PROXYv2 protocol (protocol value).
|
||||
*/
|
||||
enum pp2_protocol {
|
||||
PP2_PROT_UNSPEC = 0x0,
|
||||
@ -81,6 +81,19 @@ enum pp2_protocol {
|
||||
PP2_PROT_DGRAM = 0x2
|
||||
};
|
||||
|
||||
/**
|
||||
* Expected combinations of address family and protocol values used in checks.
|
||||
*/
|
||||
enum pp2_af_protocol_combination {
|
||||
PP2_UNSPEC_UNSPEC = (PP2_AF_UNSPEC<<4)|PP2_PROT_UNSPEC,
|
||||
PP2_INET_STREAM = (PP2_AF_INET<<4)|PP2_PROT_STREAM,
|
||||
PP2_INET_DGRAM = (PP2_AF_INET<<4)|PP2_PROT_DGRAM,
|
||||
PP2_INET6_STREAM = (PP2_AF_INET6<<4)|PP2_PROT_STREAM,
|
||||
PP2_INET6_DGRAM = (PP2_AF_INET6<<4)|PP2_PROT_DGRAM,
|
||||
PP2_UNIX_STREAM = (PP2_AF_UNIX<<4)|PP2_PROT_STREAM,
|
||||
PP2_UNIX_DGRAM = (PP2_AF_UNIX<<4)|PP2_PROT_DGRAM
|
||||
};
|
||||
|
||||
/**
|
||||
* PROXYv2 header.
|
||||
*/
|
||||
@ -109,23 +122,56 @@ struct pp2_header {
|
||||
} addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* PROXY parse errors.
|
||||
*/
|
||||
enum pp_parse_errors {
|
||||
PP_PARSE_NOERROR = 0,
|
||||
PP_PARSE_SIZE,
|
||||
PP_PARSE_WRONG_HEADERv2,
|
||||
PP_PARSE_UNKNOWN_CMD,
|
||||
PP_PARSE_UNKNOWN_FAM_PROT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the internal proxy structure.
|
||||
* @param write_uint16: pointer to a function that can write uint16.
|
||||
* @param write_uint32: pointer to a function that can write uint32.
|
||||
*/
|
||||
void pp_init(void (*write_uint16)(void* buf, uint16_t data),
|
||||
void (*write_uint32)(void* buf, uint32_t data));
|
||||
|
||||
/**
|
||||
* Lookup the parsing error description.
|
||||
* @param error: parsing error from pp2_read_header.
|
||||
* @return the description.
|
||||
*/
|
||||
const char* pp_lookup_error(enum pp_parse_errors error);
|
||||
|
||||
/**
|
||||
* Write a PROXYv2 header at the current position of the buffer.
|
||||
* @param buf: the buffer to write to.
|
||||
* @param buf: pointer to the buffer to write data to.
|
||||
* @param buflen: available size on the buffer.
|
||||
* @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,
|
||||
size_t pp2_write_to_buf(uint8_t* buf, size_t buflen,
|
||||
#ifdef INET6
|
||||
struct sockaddr_storage* src,
|
||||
#else
|
||||
struct sockaddr_in* src,
|
||||
#endif
|
||||
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.
|
||||
* @param buf: pointer to the buffer data to read from.
|
||||
* @param buflen: available size on the buffer.
|
||||
* @return parsing error, 0 on success.
|
||||
*/
|
||||
struct pp2_header* pp2_read_header(struct sldns_buffer* buf);
|
||||
int pp2_read_header(uint8_t* buf, size_t buflen);
|
||||
|
||||
#endif /* PROXY_PROTOCOL_H */
|
||||
|
@ -39,6 +39,7 @@
|
||||
* This file contains functions for RFC 1982 serial number arithmetic.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "util/rfc_1982.h"
|
||||
|
||||
int
|
||||
compare_1982(uint32_t a, uint32_t b)
|
||||
|
@ -26,6 +26,11 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
/** EDIT
|
||||
* prevent warning from -Wmissing-prototypes
|
||||
*/
|
||||
#include "util/siphash.h"
|
||||
|
||||
/* default: SipHash-2-4 */
|
||||
#define cROUNDS 2
|
||||
#define dROUNDS 4
|
||||
|
Loading…
Reference in New Issue
Block a user