sync with OpenBSD -current
This commit is contained in:
parent
9dfe537fef
commit
b467550def
72 changed files with 5497 additions and 3934 deletions
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: funcs.pl,v 1.9 2017/11/08 22:14:02 bluhm Exp $
|
||||
# $OpenBSD: funcs.pl,v 1.10 2024/06/14 15:12:57 bluhm Exp $
|
||||
|
||||
# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org>
|
||||
#
|
||||
|
@ -16,8 +16,6 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
no warnings 'experimental::smartmatch';
|
||||
use feature 'switch';
|
||||
use Errno;
|
||||
use Digest::MD5;
|
||||
use IO::Socket qw(sockatmark);
|
||||
|
@ -40,13 +38,11 @@ sub write_stream {
|
|||
$ctx->add($char);
|
||||
print $char
|
||||
or die ref($self), " print failed: $!";
|
||||
given ($char) {
|
||||
when(/9/) { $char = 'A' }
|
||||
when(/Z/) { $char = 'a' }
|
||||
when(/z/) { $char = "\n" }
|
||||
when(/\n/) { print STDERR "."; $char = '0' }
|
||||
default { $char++ }
|
||||
}
|
||||
if ($char =~ /9/) { $char = 'A' }
|
||||
elsif ($char =~ /Z/) { $char = 'a' }
|
||||
elsif ($char =~ /z/) { $char = "\n" }
|
||||
elsif ($char =~ /\n/) { print STDERR "."; $char = '0' }
|
||||
else { $char++ }
|
||||
if ($self->{sleep}) {
|
||||
IO::Handle::flush(\*STDOUT);
|
||||
sleep $self->{sleep};
|
||||
|
@ -73,8 +69,7 @@ sub write_oob {
|
|||
my $char = '0';
|
||||
for (my $i = 1; $i < $len; $i++) {
|
||||
$msg .= $char;
|
||||
given ($char) {
|
||||
when(/9/) {
|
||||
if ($char =~ /9/) {
|
||||
$ctx->add("[$char]");
|
||||
defined(send(STDOUT, $msg, MSG_OOB))
|
||||
or die ref($self), " send OOB failed: $!";
|
||||
|
@ -83,18 +78,22 @@ sub write_oob {
|
|||
sleep .1;
|
||||
$msg = "";
|
||||
$char = 'A';
|
||||
}
|
||||
when(/Z/) { $ctx->add($char); $char = 'a' }
|
||||
when(/z/) { $ctx->add($char); $char = "\n" }
|
||||
when(/\n/) {
|
||||
} elsif ($char =~ /Z/) {
|
||||
$ctx->add($char);
|
||||
$char = 'a';
|
||||
} elsif ($char =~ /z/) {
|
||||
$ctx->add($char);
|
||||
$char = "\n";
|
||||
} elsif ($char =~ /\n/) {
|
||||
$ctx->add($char);
|
||||
defined(send(STDOUT, $msg, 0))
|
||||
or die ref($self), " send failed: $!";
|
||||
print STDERR ".";
|
||||
$msg = "";
|
||||
$char = '0';
|
||||
}
|
||||
default { $ctx->add($char); $char++ }
|
||||
} else {
|
||||
$ctx->add($char);
|
||||
$char++;
|
||||
}
|
||||
}
|
||||
if ($len) {
|
||||
|
@ -125,13 +124,11 @@ sub write_datagram {
|
|||
for (my $i = 1; $i < $l; $i++) {
|
||||
$ctx->add($char);
|
||||
$string .= $char;
|
||||
given ($char) {
|
||||
when(/9/) { $char = 'A' }
|
||||
when(/Z/) { $char = 'a' }
|
||||
when(/z/) { $char = "\n" }
|
||||
when(/\n/) { $char = '0' }
|
||||
default { $char++ }
|
||||
}
|
||||
if ($char =~ /9/) { $char = 'A' }
|
||||
elsif ($char =~ /Z/) { $char = 'a' }
|
||||
elsif ($char =~ /z/) { $char = "\n" }
|
||||
elsif ($char =~ /\n/) { $char = '0' }
|
||||
else { $char++ }
|
||||
}
|
||||
if ($l) {
|
||||
$ctx->add("\n");
|
||||
|
@ -311,10 +308,12 @@ sub relay_copy {
|
|||
my $self = shift;
|
||||
my $protocol = $self->{protocol} || "tcp";
|
||||
|
||||
given ($protocol) {
|
||||
when (/tcp/) { relay_copy_stream($self, @_) }
|
||||
when (/udp/) { relay_copy_datagram($self, @_) }
|
||||
default { die ref($self), " unknown protocol name: $protocol" }
|
||||
if ($protocol =~ /tcp/) {
|
||||
relay_copy_stream($self, @_);
|
||||
} elsif ($protocol =~ /udp/) {
|
||||
relay_copy_datagram($self, @_);
|
||||
} else {
|
||||
die ref($self), " unknown protocol name: $protocol";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,10 +436,12 @@ sub relay_splice {
|
|||
my $self = shift;
|
||||
my $protocol = $self->{protocol} || "tcp";
|
||||
|
||||
given ($protocol) {
|
||||
when (/tcp/) { relay_splice_stream($self, @_) }
|
||||
when (/udp/) { relay_splice_datagram($self, @_) }
|
||||
default { die ref($self), " unknown protocol name: $protocol" }
|
||||
if ($protocol =~ /tcp/) {
|
||||
relay_splice_stream($self, @_);
|
||||
} elsif ($protocol =~ /udp/) {
|
||||
relay_splice_datagram($self, @_);
|
||||
} else {
|
||||
die ref($self), " unknown protocol name: $protocol";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,10 +449,12 @@ sub relay {
|
|||
my $self = shift;
|
||||
my $forward = $self->{forward};
|
||||
|
||||
given ($forward) {
|
||||
when (/copy/) { relay_copy($self, @_) }
|
||||
when (/splice/) { relay_splice($self, @_) }
|
||||
default { die ref($self), " unknown forward name: $forward" }
|
||||
if ($forward =~ /copy/) {
|
||||
relay_copy($self, @_);
|
||||
} elsif ($forward =~ /splice/) {
|
||||
relay_splice($self, @_);
|
||||
} else {
|
||||
die ref($self), " unknown forward name: $forward";
|
||||
}
|
||||
|
||||
my $soerror;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: Makefile,v 1.134 2024/06/06 19:49:25 djm Exp $
|
||||
# $OpenBSD: Makefile,v 1.135 2024/06/14 04:43:11 djm Exp $
|
||||
|
||||
OPENSSL?= yes
|
||||
|
||||
|
@ -103,7 +103,8 @@ LTESTS= connect \
|
|||
match-subsystem \
|
||||
agent-pkcs11-restrict \
|
||||
agent-pkcs11-cert \
|
||||
penalty
|
||||
penalty \
|
||||
penalty-expire
|
||||
|
||||
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
|
||||
INTEROP_TESTS+= dropbear-ciphers dropbear-kex
|
||||
|
|
34
regress/usr.bin/ssh/penalty-expire.sh
Normal file
34
regress/usr.bin/ssh/penalty-expire.sh
Normal file
|
@ -0,0 +1,34 @@
|
|||
# $OpenBSD
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="penalties"
|
||||
|
||||
grep -vi PerSourcePenalties $OBJ/sshd_config > $OBJ/sshd_config.bak
|
||||
cp $OBJ/authorized_keys_${USER} $OBJ/authorized_keys_${USER}.bak
|
||||
|
||||
conf() {
|
||||
test -z "$PIDFILE" || stop_sshd
|
||||
(cat $OBJ/sshd_config.bak ;
|
||||
echo "PerSourcePenalties $@") > $OBJ/sshd_config
|
||||
cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER}
|
||||
start_sshd
|
||||
}
|
||||
|
||||
conf "noauth:10s authfail:10s max:20s min:1s"
|
||||
|
||||
verbose "test connect"
|
||||
${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed"
|
||||
|
||||
verbose "penalty expiry"
|
||||
|
||||
# Incur a penalty
|
||||
cat /dev/null > $OBJ/authorized_keys_${USER}
|
||||
${SSH} -F $OBJ/ssh_config somehost true && fatal "authfail connect succeeded"
|
||||
|
||||
# Check denied
|
||||
cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER}
|
||||
${SSH} -F $OBJ/ssh_config somehost true && fatal "authfail not rejected"
|
||||
|
||||
# Let it expire and try again.
|
||||
sleep 11
|
||||
${SSH} -F $OBJ/ssh_config somehost true || fail "authfail not expired"
|
|
@ -14,7 +14,7 @@ conf() {
|
|||
start_sshd
|
||||
}
|
||||
|
||||
conf "noauth:10s authfail:6s grace-exceeded:10s min:8s max:20s"
|
||||
conf "authfail:30s min:50s max:200s"
|
||||
|
||||
verbose "test connect"
|
||||
${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed"
|
||||
|
@ -36,13 +36,10 @@ cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER}
|
|||
|
||||
# These should be refused by the active penalty
|
||||
${SSH} -F $OBJ/ssh_config somehost true && fail "authfail not rejected"
|
||||
sleep 5
|
||||
${SSH} -F $OBJ/ssh_config somehost true && fail "repeat authfail not rejected"
|
||||
|
||||
# Penalty should have expired, this should succeed.
|
||||
sleep 8
|
||||
${SSH} -F $OBJ/ssh_config somehost true || fail "authfail not expired"
|
||||
|
||||
conf "noauth:100s"
|
||||
${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed"
|
||||
verbose "penalty for no authentication"
|
||||
${SSHKEYSCAN} -t ssh-ed25519 -p $PORT 127.0.0.1 >/dev/null || fatal "keyscan failed"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: funcs.pl,v 1.9 2021/12/22 15:54:01 bluhm Exp $
|
||||
# $OpenBSD: funcs.pl,v 1.10 2024/06/14 15:12:57 bluhm Exp $
|
||||
|
||||
# Copyright (c) 2010-2021 Alexander Bluhm <bluhm@openbsd.org>
|
||||
#
|
||||
|
@ -16,10 +16,9 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
no warnings 'experimental::smartmatch';
|
||||
use feature 'switch';
|
||||
use Errno;
|
||||
use Digest::MD5;
|
||||
use POSIX;
|
||||
use Socket;
|
||||
use Socket6;
|
||||
use IO::Socket;
|
||||
|
@ -63,13 +62,11 @@ sub write_char {
|
|||
$ctx->add($char);
|
||||
print $char
|
||||
or die ref($self), " print failed: $!";
|
||||
given ($char) {
|
||||
when(/9/) { $char = 'A' }
|
||||
when(/Z/) { $char = 'a' }
|
||||
when(/z/) { $char = "\n" }
|
||||
when(/\n/) { print STDERR "."; $char = '0' }
|
||||
default { $char++ }
|
||||
}
|
||||
if ($char =~ /9/) { $char = 'A' }
|
||||
elsif ($char =~ /Z/) { $char = 'a' }
|
||||
elsif ($char =~ /z/) { $char = "\n" }
|
||||
elsif ($char =~ /\n/) { print STDERR "."; $char = '0' }
|
||||
else { $char++ }
|
||||
if ($self->{sleep}) {
|
||||
IO::Handle::flush(\*STDOUT);
|
||||
sleep $self->{sleep};
|
||||
|
@ -313,7 +310,6 @@ sub read_multipart {
|
|||
|
||||
print STDERR "LEN: ", $len, "\n";
|
||||
print STDERR "MD5: ", $ctx->hexdigest, "\n";
|
||||
|
||||
}
|
||||
|
||||
sub errignore {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: funcs.pl,v 1.25 2021/12/22 11:50:28 bluhm Exp $
|
||||
# $OpenBSD: funcs.pl,v 1.26 2024/06/14 15:12:57 bluhm Exp $
|
||||
|
||||
# Copyright (c) 2010-2021 Alexander Bluhm <bluhm@openbsd.org>
|
||||
#
|
||||
|
@ -16,8 +16,6 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
no warnings 'experimental::smartmatch';
|
||||
use feature 'switch';
|
||||
use Errno;
|
||||
use Digest::MD5;
|
||||
use Socket;
|
||||
|
@ -125,13 +123,11 @@ sub write_char {
|
|||
$ctx->add($char);
|
||||
print $char
|
||||
or die ref($self), " print failed: $!";
|
||||
given ($char) {
|
||||
when(/9/) { $char = 'A' }
|
||||
when(/Z/) { $char = 'a' }
|
||||
when(/z/) { $char = "\n" }
|
||||
when(/\n/) { print STDERR "."; $char = '0' }
|
||||
default { $char++ }
|
||||
}
|
||||
if ($char =~ /9/) { $char = 'A' }
|
||||
elsif ($char =~ /Z/) { $char = 'a' }
|
||||
elsif ($char =~ /z/) { $char = "\n" }
|
||||
elsif ($char =~ /\n/) { print STDERR "."; $char = '0' }
|
||||
else { $char++ }
|
||||
if ($self->{sleep}) {
|
||||
IO::Handle::flush(\*STDOUT);
|
||||
sleep $self->{sleep};
|
||||
|
@ -521,6 +517,15 @@ sub check_logs {
|
|||
and die "relayd lost child";
|
||||
}
|
||||
|
||||
sub array_eq {
|
||||
my ($a, $b) = @_;
|
||||
return if @$a != @$b;
|
||||
for (my $i = 0; $i < @$a; $i++) {
|
||||
return if $$a[$i] ne $$b[$i];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub check_len {
|
||||
my ($c, $r, $s, %args) = @_;
|
||||
|
||||
|
@ -531,7 +536,7 @@ sub check_len {
|
|||
unless $args{client}{nocheck};
|
||||
@slen = $s->loggrep(qr/^LEN: /) or die "no server len"
|
||||
unless $args{server}{nocheck};
|
||||
!@clen || !@slen || @clen ~~ @slen
|
||||
!@clen || !@slen || array_eq \@clen, \@slen
|
||||
or die "client: @clen", "server: @slen", "len mismatch";
|
||||
!defined($args{len}) || !$clen[0] || $clen[0] eq "LEN: $args{len}\n"
|
||||
or die "client: $clen[0]", "len $args{len} expected";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: funcs.pl,v 1.40 2022/03/25 14:15:10 bluhm Exp $
|
||||
# $OpenBSD: funcs.pl,v 1.41 2024/06/14 15:12:57 bluhm Exp $
|
||||
|
||||
# Copyright (c) 2010-2021 Alexander Bluhm <bluhm@openbsd.org>
|
||||
#
|
||||
|
@ -16,8 +16,6 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
no warnings 'experimental::smartmatch';
|
||||
use feature 'switch';
|
||||
use Errno;
|
||||
use List::Util qw(first);
|
||||
use Socket;
|
||||
|
@ -152,12 +150,10 @@ sub generate_chars {
|
|||
my $char = '0';
|
||||
for (my $i = 0; $i < $len; $i++) {
|
||||
$msg .= $char;
|
||||
given ($char) {
|
||||
when(/9/) { $char = 'A' }
|
||||
when(/Z/) { $char = 'a' }
|
||||
when(/z/) { $char = '0' }
|
||||
default { $char++ }
|
||||
}
|
||||
if ($char =~ /9/) { $char = 'A' }
|
||||
elsif ($char =~ /Z/) { $char = 'a' }
|
||||
elsif ($char =~ /z/) { $char = '0' }
|
||||
else { $char++ }
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
|
|
@ -380,8 +380,8 @@
|
|||
/* Define to 1 if you have the `memmove' function. */
|
||||
#define HAVE_MEMMOVE 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
/* #undef HAVE_MINIX_CONFIG_H */
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#define HAVE_NETDB_H 1
|
||||
|
@ -588,6 +588,9 @@
|
|||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
|
@ -690,6 +693,9 @@
|
|||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
/* #undef HAVE_VFORK_H */
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#define HAVE_WCHAR_H 1
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
/* #undef HAVE_WINDOWS_H */
|
||||
|
||||
|
@ -773,7 +779,7 @@
|
|||
#define PACKAGE_NAME "unbound"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "unbound 1.19.3"
|
||||
#define PACKAGE_STRING "unbound 1.20.0"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "unbound"
|
||||
|
@ -782,7 +788,7 @@
|
|||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.19.3"
|
||||
#define PACKAGE_VERSION "1.20.0"
|
||||
|
||||
/* default pidfile location */
|
||||
#define PIDFILE ""
|
||||
|
@ -805,7 +811,7 @@
|
|||
#define ROOT_CERT_FILE "/var/unbound/etc/icannbundle.pem"
|
||||
|
||||
/* version number for resource files */
|
||||
#define RSRC_PACKAGE_VERSION 1,19,3,0
|
||||
#define RSRC_PACKAGE_VERSION 1,20,0,0
|
||||
|
||||
/* Directory to chdir to */
|
||||
#define RUN_DIR "/var/unbound/etc"
|
||||
|
@ -831,7 +837,9 @@
|
|||
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
||||
/* #undef SODIUM_MISUSE_HANDLER */
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* use default strptime. */
|
||||
|
@ -927,21 +935,87 @@
|
|||
#ifndef _ALL_SOURCE
|
||||
# define _ALL_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on macOS. */
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
# define _DARWIN_C_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# define __EXTENSIONS__ 1
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
/* Enable X/Open compliant socket functions that do not require linking
|
||||
with -lxnet on HP-UX 11.11. */
|
||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
# define _HPUX_ALT_XOPEN_SOCKET_API 1
|
||||
#endif
|
||||
/* Identify the host operating system as Minix.
|
||||
This macro does not affect the system headers' behavior.
|
||||
A future release of Autoconf may stop defining this macro. */
|
||||
#ifndef _MINIX
|
||||
/* # undef _MINIX */
|
||||
#endif
|
||||
/* Enable general extensions on NetBSD.
|
||||
Enable NetBSD compatibility extensions on Minix. */
|
||||
#ifndef _NETBSD_SOURCE
|
||||
# define _NETBSD_SOURCE 1
|
||||
#endif
|
||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
||||
Oddly enough, this does nothing on OpenBSD. */
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
# define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
/* # undef _POSIX_SOURCE */
|
||||
#endif
|
||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_1_SOURCE
|
||||
/* # undef _POSIX_1_SOURCE */
|
||||
#endif
|
||||
/* Enable POSIX-compatible threading on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
# define __STDC_WANT_IEC_60559_BFP_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
||||
#ifndef __STDC_WANT_LIB_EXT2__
|
||||
# define __STDC_WANT_LIB_EXT2__ 1
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
# define __STDC_WANT_MATH_SPEC_FUNCS__ 1
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# define _TANDEM_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# define __EXTENSIONS__ 1
|
||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||
to make mbstate_t available. */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
/* # undef _XOPEN_SOURCE */
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -967,11 +1041,6 @@
|
|||
`char[]'. */
|
||||
#define YYTEXT_POINTER 1
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
|
@ -981,18 +1050,8 @@
|
|||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
/* #undef _MINIX */
|
||||
|
||||
/* Enable for compile on Minix */
|
||||
/* #undef _NETBSD_SOURCE */
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
/* #undef _POSIX_1_SOURCE */
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
/* #undef _POSIX_SOURCE */
|
||||
#define _NETBSD_SOURCE 1
|
||||
|
||||
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
||||
compiled for windows. */
|
||||
|
@ -1034,7 +1093,7 @@
|
|||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
/* #undef off_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to 'int' if not defined */
|
||||
|
|
|
@ -71,6 +71,7 @@ forwards_create(void)
|
|||
sizeof(struct iter_forwards));
|
||||
if(!fwd)
|
||||
return NULL;
|
||||
lock_rw_init(&fwd->lock);
|
||||
return fwd;
|
||||
}
|
||||
|
||||
|
@ -100,6 +101,7 @@ forwards_delete(struct iter_forwards* fwd)
|
|||
{
|
||||
if(!fwd)
|
||||
return;
|
||||
lock_rw_destroy(&fwd->lock);
|
||||
fwd_del_tree(fwd);
|
||||
free(fwd);
|
||||
}
|
||||
|
@ -332,45 +334,64 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
|||
int
|
||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
if(fwd->tree) {
|
||||
lock_unprotect(&fwd->lock, fwd->tree);
|
||||
}
|
||||
fwd_del_tree(fwd);
|
||||
fwd->tree = rbtree_create(fwd_cmp);
|
||||
if(!fwd->tree)
|
||||
return 0;
|
||||
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
|
||||
|
||||
lock_rw_wrlock(&fwd->lock);
|
||||
/* read forward zones */
|
||||
if(!read_forwards(fwd, cfg))
|
||||
if(!read_forwards(fwd, cfg)) {
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 0;
|
||||
if(!make_stub_holes(fwd, cfg))
|
||||
}
|
||||
if(!make_stub_holes(fwd, cfg)) {
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
||||
int nolock)
|
||||
{
|
||||
rbnode_type* res = NULL;
|
||||
struct iter_forward_zone* res;
|
||||
struct iter_forward_zone key;
|
||||
int has_dp;
|
||||
key.node.key = &key;
|
||||
key.dclass = qclass;
|
||||
key.name = qname;
|
||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||
res = rbtree_search(fwd->tree, &key);
|
||||
if(res) return ((struct iter_forward_zone*)res)->dp;
|
||||
return NULL;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
||||
res = (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
||||
has_dp = res && res->dp;
|
||||
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return has_dp?res->dp:NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
||||
int nolock)
|
||||
{
|
||||
/* lookup the forward zone in the tree */
|
||||
rbnode_type* res = NULL;
|
||||
struct iter_forward_zone *result;
|
||||
struct iter_forward_zone key;
|
||||
int has_dp;
|
||||
key.node.key = &key;
|
||||
key.dclass = qclass;
|
||||
key.name = qname;
|
||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
||||
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
|
||||
/* exact */
|
||||
result = (struct iter_forward_zone*)res;
|
||||
|
@ -378,8 +399,10 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
|||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct iter_forward_zone*)res;
|
||||
if(!result || result->dclass != qclass)
|
||||
if(!result || result->dclass != qclass) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return NULL;
|
||||
}
|
||||
/* count number of labels matched */
|
||||
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
||||
key.namelabs, &m);
|
||||
|
@ -389,20 +412,22 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
|||
result = result->parent;
|
||||
}
|
||||
}
|
||||
if(result)
|
||||
return result->dp;
|
||||
return NULL;
|
||||
has_dp = result && result->dp;
|
||||
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return has_dp?result->dp:NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass)
|
||||
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass, int nolock)
|
||||
{
|
||||
uint8_t root = 0;
|
||||
return forwards_lookup(fwd, &root, qclass);
|
||||
return forwards_lookup(fwd, &root, qclass, nolock);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
/* Finds next root item in forwards lookup tree.
|
||||
* Caller needs to handle locking of the forwards structure. */
|
||||
static int
|
||||
next_root_locked(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
rbnode_type* n;
|
||||
|
@ -419,7 +444,7 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
|||
}
|
||||
/* root not first item? search for higher items */
|
||||
*dclass = p->dclass + 1;
|
||||
return forwards_next_root(fwd, dclass);
|
||||
return next_root_locked(fwd, dclass);
|
||||
}
|
||||
/* find class n in tree, we may get a direct hit, or if we don't
|
||||
* this is the last item of the previous class so rbtree_next() takes
|
||||
|
@ -447,10 +472,21 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
|||
}
|
||||
/* not a root node, return next higher item */
|
||||
*dclass = p->dclass+1;
|
||||
return forwards_next_root(fwd, dclass);
|
||||
return next_root_locked(fwd, dclass);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass, int nolock)
|
||||
{
|
||||
int ret;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
||||
ret = next_root_locked(fwd, dclass);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
forwards_get_mem(struct iter_forwards* fwd)
|
||||
{
|
||||
|
@ -458,10 +494,12 @@ forwards_get_mem(struct iter_forwards* fwd)
|
|||
size_t s;
|
||||
if(!fwd)
|
||||
return 0;
|
||||
lock_rw_rdlock(&fwd->lock);
|
||||
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
||||
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
||||
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
||||
}
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -477,49 +515,78 @@ fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|||
}
|
||||
|
||||
int
|
||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
}
|
||||
if(!forwards_insert(fwd, c, dp))
|
||||
if(!forwards_insert(fwd, c, dp)) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if(!(z=fwd_zone_find(fwd, c, nm))) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return; /* nothing to do */
|
||||
}
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
int nolock)
|
||||
{
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if(fwd_zone_find(fwd, c, nm) != NULL) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 1; /* already a stub zone there */
|
||||
}
|
||||
if(!fwd_add_stub_hole(fwd, c, nm)) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm, int nolock)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if(!(z=fwd_zone_find(fwd, c, nm))) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return; /* nothing to do */
|
||||
if(z->dp != NULL)
|
||||
}
|
||||
if(z->dp != NULL) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return; /* not a stub hole */
|
||||
}
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#ifndef ITERATOR_ITER_FWD_H
|
||||
#define ITERATOR_ITER_FWD_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
|
||||
|
@ -50,6 +51,11 @@ struct delegpt;
|
|||
* Iterator forward zones structure
|
||||
*/
|
||||
struct iter_forwards {
|
||||
/** lock on the forwards tree.
|
||||
* When grabbing both this lock and the anchors.lock, this lock
|
||||
* is grabbed first. When grabbing both this lock and the hints.lock
|
||||
* this lock is grabbed first. */
|
||||
lock_rw_type lock;
|
||||
/**
|
||||
* Zones are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
|
@ -106,47 +112,65 @@ int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
|
|||
|
||||
/**
|
||||
* Find forward zone exactly by name
|
||||
* The return value is contents of the forwards structure.
|
||||
* Caller should lock and unlock a readlock on the forwards structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the forwards structure if a
|
||||
* value was returned.
|
||||
* @param fwd: forward storage.
|
||||
* @param qname: The qname of the query.
|
||||
* @param qclass: The qclass of the query.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A delegation point or null.
|
||||
*/
|
||||
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
|
||||
uint16_t qclass);
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Find forward zone information
|
||||
* For this qname/qclass find forward zone information, returns delegation
|
||||
* point with server names and addresses, or NULL if no forwarding is needed.
|
||||
* The return value is contents of the forwards structure.
|
||||
* Caller should lock and unlock a readlock on the forwards structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the forwards structure if a
|
||||
* value was returned.
|
||||
*
|
||||
* @param fwd: forward storage.
|
||||
* @param qname: The qname of the query.
|
||||
* @param qclass: The qclass of the query.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A delegation point if the query has to be forwarded to that list,
|
||||
* otherwise null.
|
||||
*/
|
||||
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
|
||||
uint8_t* qname, uint16_t qclass);
|
||||
uint8_t* qname, uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Same as forwards_lookup, but for the root only
|
||||
* @param fwd: forward storage.
|
||||
* @param qclass: The qclass of the query.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A delegation point if root forward exists, otherwise null.
|
||||
*/
|
||||
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
|
||||
uint16_t qclass);
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Find next root item in forwards lookup tree.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a readlock on the forwards structure.
|
||||
* @param fwd: the forward storage
|
||||
* @param qclass: class to look at next, or higher.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false if none found, or if true stored in qclass.
|
||||
*/
|
||||
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass);
|
||||
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass,
|
||||
int nolock);
|
||||
|
||||
/**
|
||||
* Get memory in use by forward storage
|
||||
* Locks and unlocks the structure.
|
||||
* @param fwd: forward storage.
|
||||
* @return bytes in use
|
||||
*/
|
||||
|
@ -158,42 +182,56 @@ int fwd_cmp(const void* k1, const void* k2);
|
|||
/**
|
||||
* Add zone to forward structure. For external use since it recalcs
|
||||
* the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* forward zone. malloced.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
struct delegpt* dp);
|
||||
struct delegpt* dp, int nolock);
|
||||
|
||||
/**
|
||||
* Remove zone from forward structure. For external use since it
|
||||
* recalcs the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
*/
|
||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
/**
|
||||
* Add stub hole (empty entry in forward table, that makes resolution skip
|
||||
* a forward-zone because the stub zone should override the forward zone).
|
||||
* Does not add one if not necessary.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
/**
|
||||
* Remove stub hole, if one exists.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
*/
|
||||
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm);
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
#endif /* ITERATOR_ITER_FWD_H */
|
||||
|
|
|
@ -57,6 +57,8 @@ hints_create(void)
|
|||
sizeof(struct iter_hints));
|
||||
if(!hints)
|
||||
return NULL;
|
||||
lock_rw_init(&hints->lock);
|
||||
lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
|
||||
return hints;
|
||||
}
|
||||
|
||||
|
@ -83,6 +85,7 @@ hints_delete(struct iter_hints* hints)
|
|||
{
|
||||
if(!hints)
|
||||
return;
|
||||
lock_rw_destroy(&hints->lock);
|
||||
hints_del_tree(hints);
|
||||
free(hints);
|
||||
}
|
||||
|
@ -438,47 +441,70 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
|
|||
int
|
||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
int nolock = 1;
|
||||
lock_rw_wrlock(&hints->lock);
|
||||
hints_del_tree(hints);
|
||||
name_tree_init(&hints->tree);
|
||||
|
||||
/* read root hints */
|
||||
if(!read_root_hints_list(hints, cfg))
|
||||
return 0;
|
||||
|
||||
/* read stub hints */
|
||||
if(!read_stubs(hints, cfg))
|
||||
return 0;
|
||||
|
||||
/* use fallback compiletime root hints */
|
||||
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
||||
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
||||
cfg->do_ip6);
|
||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||
if(!dp)
|
||||
return 0;
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
|
||||
if(!read_root_hints_list(hints, cfg)) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read stub hints */
|
||||
if(!read_stubs(hints, cfg)) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* use fallback compiletime root hints */
|
||||
if(!hints_find_root(hints, LDNS_RR_CLASS_IN, nolock)) {
|
||||
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
||||
cfg->do_ip6);
|
||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||
if(!dp) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
}
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
name_tree_init_parents(&hints->tree);
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
|
||||
hints_find(struct iter_hints* hints, uint8_t* qname, uint16_t qclass,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_hints_stub *stub;
|
||||
size_t len;
|
||||
int has_dp;
|
||||
int labs = dname_count_size_labels(qname, &len);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
||||
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
qname, len, labs, qclass);
|
||||
has_dp = stub && stub->dp;
|
||||
if(!has_dp && !nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return has_dp?stub->dp:NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
hints_find_root(struct iter_hints* hints, uint16_t qclass, int nolock)
|
||||
{
|
||||
uint8_t rootlab = 0;
|
||||
struct iter_hints_stub *stub;
|
||||
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
&rootlab, 1, 1, qclass);
|
||||
if(!stub)
|
||||
return NULL;
|
||||
return stub->dp;
|
||||
return hints_find(hints, &rootlab, qclass, nolock);
|
||||
}
|
||||
|
||||
struct iter_hints_stub*
|
||||
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
uint16_t qclass, struct delegpt* cache_dp)
|
||||
uint16_t qclass, struct delegpt* cache_dp, int nolock)
|
||||
{
|
||||
size_t len;
|
||||
int labs;
|
||||
|
@ -486,14 +512,20 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
|||
|
||||
/* first lookup the stub */
|
||||
labs = dname_count_size_labels(qname, &len);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
||||
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
|
||||
len, labs, qclass);
|
||||
if(!r) return NULL;
|
||||
if(!r) {
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If there is no cache (root prime situation) */
|
||||
if(cache_dp == NULL) {
|
||||
if(r->dp->namelabs != 1)
|
||||
return r; /* no cache dp, use any non-root stub */
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -510,12 +542,18 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
|||
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
|
||||
cache_dp->name, cache_dp->namelabs))
|
||||
return r; /* need to prime this stub */
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock)
|
||||
{
|
||||
return name_tree_next_root(&hints->tree, qclass);
|
||||
int ret;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
||||
ret = name_tree_next_root(&hints->tree, qclass);
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -524,39 +562,52 @@ hints_get_mem(struct iter_hints* hints)
|
|||
size_t s;
|
||||
struct iter_hints_stub* p;
|
||||
if(!hints) return 0;
|
||||
lock_rw_rdlock(&hints->lock);
|
||||
s = sizeof(*hints);
|
||||
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
||||
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
||||
}
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime)
|
||||
int noprime, int nolock)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&hints->lock); }
|
||||
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
}
|
||||
if(!hints_insert(hints, c, dp, noprime))
|
||||
if(!hints_insert(hints, c, dp, noprime)) {
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return 0;
|
||||
}
|
||||
name_tree_init_parents(&hints->tree);
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
|
||||
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
size_t len;
|
||||
int labs = dname_count_size_labels(nm, &len);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&hints->lock); }
|
||||
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
nm, len, labs, c)))
|
||||
nm, len, labs, c))) {
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return; /* nothing to do */
|
||||
}
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
name_tree_init_parents(&hints->tree);
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#ifndef ITERATOR_ITER_HINTS_H
|
||||
#define ITERATOR_ITER_HINTS_H
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "util/locks.h"
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
|
@ -51,6 +52,10 @@ struct delegpt;
|
|||
* Iterator hints structure
|
||||
*/
|
||||
struct iter_hints {
|
||||
/** lock on the forwards tree.
|
||||
* When grabbing both this lock and the anchors.lock, this lock
|
||||
* is grabbed first. */
|
||||
lock_rw_type lock;
|
||||
/**
|
||||
* Hints are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
|
@ -95,42 +100,70 @@ void hints_delete(struct iter_hints* hints);
|
|||
int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Find root hints for the given class.
|
||||
* Find hints for the given class.
|
||||
* The return value is contents of the hints structure.
|
||||
* Caller should lock and unlock a readlock on the hints structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the hints structure if a
|
||||
* value was returned.
|
||||
* @param hints: hint storage.
|
||||
* @param qname: the qname that generated the delegation point.
|
||||
* @param qclass: class for which root hints are requested. host order.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: NULL if no hints, or a ptr to stored hints.
|
||||
*/
|
||||
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
|
||||
struct delegpt* hints_find(struct iter_hints* hints, uint8_t* qname,
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Same as hints_lookup, but for the root only.
|
||||
* @param hints: hint storage.
|
||||
* @param qclass: class for which root hints are requested. host order.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: NULL if no hints, or a ptr to stored hints.
|
||||
*/
|
||||
struct delegpt* hints_find_root(struct iter_hints* hints,
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Find next root hints (to cycle through all root hints).
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a readlock on the hints structure.
|
||||
* @param hints: hint storage
|
||||
* @param qclass: class for which root hints are sought.
|
||||
* 0 means give the first available root hints class.
|
||||
* x means, give class x or a higher class if any.
|
||||
* returns the found class in this variable.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return true if a root hint class is found.
|
||||
* false if not root hint class is found (qclass may have been changed).
|
||||
*/
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass);
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Given a qname/qclass combination, and the delegation point from the cache
|
||||
* for this qname/qclass, determine if this combination indicates that a
|
||||
* stub hint exists and must be primed.
|
||||
* The return value is contents of the hints structure.
|
||||
* Caller should lock and unlock a readlock on the hints structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the hints structure if a
|
||||
* value was returned.
|
||||
*
|
||||
* @param hints: hint storage.
|
||||
* @param qname: The qname that generated the delegation point.
|
||||
* @param qclass: The qclass that generated the delegation point.
|
||||
* @param dp: The cache generated delegation point.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A priming delegation point if there is a stub hint that must
|
||||
* be primed, otherwise null.
|
||||
*/
|
||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
|
||||
|
||||
/**
|
||||
* Get memory in use by hints
|
||||
* Locks and unlocks the structure.
|
||||
* @param hints: hint storage.
|
||||
* @return bytes in use
|
||||
*/
|
||||
|
@ -139,23 +172,30 @@ size_t hints_get_mem(struct iter_hints* hints);
|
|||
/**
|
||||
* Add stub to hints structure. For external use since it recalcs
|
||||
* the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the hints structure.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* hints stub. malloced.
|
||||
* @param noprime: set noprime option to true or false on new hint stub.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime);
|
||||
int noprime, int nolock);
|
||||
|
||||
/**
|
||||
* Remove stub from hints structure. For external use since it
|
||||
* recalcs the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the hints structure.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of stub zone
|
||||
* @param nm: name of stub zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
*/
|
||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
|
||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
#endif /* ITERATOR_ITER_HINTS_H */
|
||||
|
|
|
@ -1284,8 +1284,17 @@ iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
|
|||
uint16_t* c)
|
||||
{
|
||||
uint16_t c1 = *c, c2 = *c;
|
||||
int r1 = hints_next_root(hints, &c1);
|
||||
int r2 = forwards_next_root(fwd, &c2);
|
||||
int r1, r2;
|
||||
int nolock = 1;
|
||||
|
||||
/* prelock both forwards and hints for atomic read. */
|
||||
lock_rw_rdlock(&fwd->lock);
|
||||
lock_rw_rdlock(&hints->lock);
|
||||
r1 = hints_next_root(hints, &c1, nolock);
|
||||
r2 = forwards_next_root(fwd, &c2, nolock);
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
lock_rw_unlock(&hints->lock);
|
||||
|
||||
if(!r1 && !r2) /* got none, end of list */
|
||||
return 0;
|
||||
else if(!r1) /* got one, return that */
|
||||
|
@ -1450,15 +1459,21 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
|
|||
|
||||
int
|
||||
iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
uint8_t** retdpname, size_t* retdpnamelen)
|
||||
uint8_t** retdpname, size_t* retdpnamelen, uint8_t* dpname_storage,
|
||||
size_t dpname_storage_len)
|
||||
{
|
||||
struct iter_hints_stub *stub;
|
||||
struct delegpt *dp;
|
||||
int nolock = 1;
|
||||
|
||||
/* Check for stub. */
|
||||
/* Lock both forwards and hints for atomic read. */
|
||||
lock_rw_rdlock(&qstate->env->fwds->lock);
|
||||
lock_rw_rdlock(&qstate->env->hints->lock);
|
||||
stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
|
||||
qinf->qclass, NULL);
|
||||
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
|
||||
qinf->qclass, NULL, nolock);
|
||||
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass,
|
||||
nolock);
|
||||
|
||||
/* see if forward or stub is more pertinent */
|
||||
if(stub && stub->dp && dp) {
|
||||
|
@ -1472,7 +1487,9 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
|||
|
||||
/* check stub */
|
||||
if (stub != NULL && stub->dp != NULL) {
|
||||
if(stub->dp->no_cache) {
|
||||
int stub_no_cache = stub->dp->no_cache;
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
if(stub_no_cache) {
|
||||
char qname[255+1];
|
||||
char dpname[255+1];
|
||||
dname_str(qinf->qname, qname);
|
||||
|
@ -1480,15 +1497,27 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
|||
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
if(retdpname) {
|
||||
*retdpname = stub->dp->name;
|
||||
if(stub->dp->namelen > dpname_storage_len) {
|
||||
verbose(VERB_ALGO, "no cache stub dpname too long");
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
*retdpname = NULL;
|
||||
*retdpnamelen = 0;
|
||||
return stub_no_cache;
|
||||
}
|
||||
memmove(dpname_storage, stub->dp->name,
|
||||
stub->dp->namelen);
|
||||
*retdpname = dpname_storage;
|
||||
*retdpnamelen = stub->dp->namelen;
|
||||
}
|
||||
return (stub->dp->no_cache);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
return stub_no_cache;
|
||||
}
|
||||
|
||||
/* Check for forward. */
|
||||
if (dp) {
|
||||
if(dp->no_cache) {
|
||||
int dp_no_cache = dp->no_cache;
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(dp_no_cache) {
|
||||
char qname[255+1];
|
||||
char dpname[255+1];
|
||||
dname_str(qinf->qname, qname);
|
||||
|
@ -1496,11 +1525,22 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
|||
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
if(retdpname) {
|
||||
*retdpname = dp->name;
|
||||
if(dp->namelen > dpname_storage_len) {
|
||||
verbose(VERB_ALGO, "no cache dpname too long");
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
*retdpname = NULL;
|
||||
*retdpnamelen = 0;
|
||||
return dp_no_cache;
|
||||
}
|
||||
memmove(dpname_storage, dp->name, dp->namelen);
|
||||
*retdpname = dpname_storage;
|
||||
*retdpnamelen = dp->namelen;
|
||||
}
|
||||
return (dp->no_cache);
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
return dp_no_cache;
|
||||
}
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(retdpname) {
|
||||
*retdpname = NULL;
|
||||
*retdpnamelen = 0;
|
||||
|
|
|
@ -407,10 +407,14 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
|
|||
* Used for NXDOMAIN checks, above that it is an nxdomain from a
|
||||
* different server and zone. You can pass NULL to not get it.
|
||||
* @param retdpnamelen: returns the length of the dpname.
|
||||
* @param dpname_storage: this is where the dpname buf is stored, if any.
|
||||
* So that caller can manage the buffer.
|
||||
* @param dpname_storage_len: size of dpname_storage buffer.
|
||||
* @return true if no_cache is set in stub or fwd.
|
||||
*/
|
||||
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
|
||||
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen);
|
||||
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen,
|
||||
uint8_t* dpname_storage, size_t dpname_storage_len);
|
||||
|
||||
/**
|
||||
* Set support for IP4 and IP6 depending on outgoing interfaces
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "iterator/iter_priv.h"
|
||||
#include "validator/val_neg.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/authzone.h"
|
||||
#include "util/module.h"
|
||||
|
@ -678,30 +679,40 @@ errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
|
|||
|
||||
/** see if last resort is possible - does config allow queries to parent */
|
||||
static int
|
||||
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
|
||||
uint16_t qclass, struct delegpt** retdp)
|
||||
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t ATTR_UNUSED(nmlen),
|
||||
uint16_t qclass, int* have_dp, struct delegpt** retdp,
|
||||
struct regional* region)
|
||||
{
|
||||
struct delegpt* fwddp;
|
||||
struct iter_hints_stub* stub;
|
||||
int labs = dname_count_labels(nm);
|
||||
struct delegpt* dp = NULL;
|
||||
int nolock = 0;
|
||||
/* do not process a last resort (the parent side) if a stub
|
||||
* or forward is configured, because we do not want to go 'above'
|
||||
* the configured servers */
|
||||
if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
|
||||
name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
|
||||
if(!dname_is_root(nm) &&
|
||||
(dp = hints_find(env->hints, nm, qclass, nolock)) &&
|
||||
/* has_parent side is turned off for stub_first, where we
|
||||
* are allowed to go to the parent */
|
||||
stub->dp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = stub->dp;
|
||||
dp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = delegpt_copy(dp, region);
|
||||
lock_rw_unlock(&env->hints->lock);
|
||||
if(have_dp) *have_dp = 1;
|
||||
return 0;
|
||||
}
|
||||
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
|
||||
if(dp) {
|
||||
lock_rw_unlock(&env->hints->lock);
|
||||
dp = NULL;
|
||||
}
|
||||
if((dp = forwards_find(env->fwds, nm, qclass, nolock)) &&
|
||||
/* has_parent_side is turned off for forward_first, where
|
||||
* we are allowed to go to the parent */
|
||||
fwddp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = fwddp;
|
||||
dp->has_parent_side_NS) {
|
||||
if(retdp) *retdp = delegpt_copy(dp, region);
|
||||
lock_rw_unlock(&env->fwds->lock);
|
||||
if(have_dp) *have_dp = 1;
|
||||
return 0;
|
||||
}
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(dp) { lock_rw_unlock(&env->fwds->lock); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -877,10 +888,11 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
{
|
||||
struct delegpt* dp;
|
||||
struct module_qstate* subq;
|
||||
int nolock = 0;
|
||||
verbose(VERB_DETAIL, "priming . %s NS",
|
||||
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)?
|
||||
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)->name:"??");
|
||||
dp = hints_lookup_root(qstate->env->hints, qclass);
|
||||
dp = hints_find_root(qstate->env->hints, qclass, nolock);
|
||||
if(!dp) {
|
||||
verbose(VERB_ALGO, "Cannot prime due to lack of hints");
|
||||
return 0;
|
||||
|
@ -890,6 +902,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS,
|
||||
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
|
||||
&subq, 0, 0)) {
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
verbose(VERB_ALGO, "could not prime root");
|
||||
return 0;
|
||||
}
|
||||
|
@ -900,6 +913,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
* copy dp, it is now part of the root prime query.
|
||||
* dp was part of in the fixed hints structure. */
|
||||
subiq->dp = delegpt_copy(dp, subq->region);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(!subiq->dp) {
|
||||
log_err("out of memory priming root, copydp");
|
||||
fptr_ok(fptr_whitelist_modenv_kill_sub(
|
||||
|
@ -911,6 +925,8 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
subiq->num_target_queries = 0;
|
||||
subiq->dnssec_expected = iter_indicates_dnssec(
|
||||
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
|
||||
} else {
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
}
|
||||
|
||||
/* this module stops, our submodule starts, and does the query. */
|
||||
|
@ -941,18 +957,21 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
struct iter_hints_stub* stub;
|
||||
struct delegpt* stub_dp;
|
||||
struct module_qstate* subq;
|
||||
int nolock = 0;
|
||||
|
||||
if(!qname) return 0;
|
||||
stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp);
|
||||
stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp,
|
||||
nolock);
|
||||
/* The stub (if there is one) does not need priming. */
|
||||
if(!stub)
|
||||
return 0;
|
||||
if(!stub) return 0;
|
||||
stub_dp = stub->dp;
|
||||
/* if we have an auth_zone dp, and stub is equal, don't prime stub
|
||||
* yet, unless we want to fallback and avoid the auth_zone */
|
||||
if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp &&
|
||||
query_dname_compare(iq->dp->name, stub_dp->name) == 0)
|
||||
query_dname_compare(iq->dp->name, stub_dp->name) == 0) {
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* is it a noprime stub (always use) */
|
||||
if(stub->noprime) {
|
||||
|
@ -961,13 +980,14 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
/* copy the dp out of the fixed hints structure, so that
|
||||
* it can be changed when servicing this query */
|
||||
iq->dp = delegpt_copy(stub_dp, qstate->region);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory priming stub");
|
||||
errinf(qstate, "malloc failure, priming stub");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return 1; /* return 1 to make module stop, with error */
|
||||
}
|
||||
log_nametypeclass(VERB_DETAIL, "use stub", stub_dp->name,
|
||||
log_nametypeclass(VERB_DETAIL, "use stub", iq->dp->name,
|
||||
LDNS_RR_TYPE_NS, qclass);
|
||||
return r;
|
||||
}
|
||||
|
@ -981,6 +1001,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
if(!generate_sub_request(stub_dp->name, stub_dp->namelen,
|
||||
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
|
||||
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) {
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
verbose(VERB_ALGO, "could not prime stub");
|
||||
errinf(qstate, "could not generate lookup for stub prime");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
|
@ -993,6 +1014,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
/* Set the initial delegation point to the hint. */
|
||||
/* make copy to avoid use of stub dp by different qs/threads */
|
||||
subiq->dp = delegpt_copy(stub_dp, subq->region);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(!subiq->dp) {
|
||||
log_err("out of memory priming stub, copydp");
|
||||
fptr_ok(fptr_whitelist_modenv_kill_sub(
|
||||
|
@ -1009,6 +1031,8 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|||
subiq->wait_priming_stub = 1;
|
||||
subiq->dnssec_expected = iter_indicates_dnssec(
|
||||
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
|
||||
} else {
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
}
|
||||
|
||||
/* this module stops, our submodule starts, and does the query. */
|
||||
|
@ -1181,7 +1205,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
|||
if(iq->depth == ie->max_dependency_depth)
|
||||
return;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass, NULL))
|
||||
iq->qchase.qclass, NULL, NULL, NULL))
|
||||
return;
|
||||
/* is this query the same as the nscheck? */
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
|
||||
|
@ -1294,6 +1318,7 @@ forward_request(struct module_qstate* qstate, struct iter_qstate* iq)
|
|||
struct delegpt* dp;
|
||||
uint8_t* delname = iq->qchase.qname;
|
||||
size_t delnamelen = iq->qchase.qname_len;
|
||||
int nolock = 0;
|
||||
if(iq->refetch_glue && iq->dp) {
|
||||
delname = iq->dp->name;
|
||||
delnamelen = iq->dp->namelen;
|
||||
|
@ -1302,12 +1327,13 @@ forward_request(struct module_qstate* qstate, struct iter_qstate* iq)
|
|||
if( (iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue)
|
||||
&& !dname_is_root(iq->qchase.qname))
|
||||
dname_remove_label(&delname, &delnamelen);
|
||||
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass);
|
||||
if(!dp)
|
||||
return 0;
|
||||
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass,
|
||||
nolock);
|
||||
if(!dp) return 0;
|
||||
/* send recursion desired to forward addr */
|
||||
iq->chase_flags |= BIT_RD;
|
||||
iq->dp = delegpt_copy(dp, qstate->region);
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
/* iq->dp checked by caller */
|
||||
verbose(VERB_ALGO, "forwarding request");
|
||||
return 1;
|
||||
|
@ -1335,6 +1361,7 @@ static int
|
|||
processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct iter_env* ie, int id)
|
||||
{
|
||||
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
|
||||
uint8_t* delname, *dpname=NULL;
|
||||
size_t delnamelen, dpnamelen=0;
|
||||
struct dns_msg* msg = NULL;
|
||||
|
@ -1381,7 +1408,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
if (iq->refetch_glue &&
|
||||
iq->dp &&
|
||||
!can_have_last_resort(qstate->env, iq->dp->name,
|
||||
iq->dp->namelen, iq->qchase.qclass, NULL)) {
|
||||
iq->dp->namelen, iq->qchase.qclass, NULL, NULL, NULL)) {
|
||||
iq->refetch_glue = 0;
|
||||
}
|
||||
|
||||
|
@ -1390,7 +1417,60 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
/* This either results in a query restart (CNAME cache response), a
|
||||
* terminating response (ANSWER), or a cache miss (null). */
|
||||
|
||||
if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen)) {
|
||||
/* Check RPZ for override */
|
||||
if(qstate->env->auth_zones) {
|
||||
/* apply rpz qname triggers, like after cname */
|
||||
struct dns_msg* forged_response =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
if(forged_response) {
|
||||
uint8_t* sname = 0;
|
||||
size_t slen = 0;
|
||||
int count = 0;
|
||||
while(forged_response && reply_find_rrset_section_an(
|
||||
forged_response->rep, iq->qchase.qname,
|
||||
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
|
||||
iq->qchase.qclass) &&
|
||||
iq->qchase.qtype != LDNS_RR_TYPE_CNAME &&
|
||||
count++ < ie->max_query_restarts) {
|
||||
/* another cname to follow */
|
||||
if(!handle_cname_response(qstate, iq, forged_response,
|
||||
&sname, &slen)) {
|
||||
errinf(qstate, "malloc failure, CNAME info");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = slen;
|
||||
forged_response =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
}
|
||||
if(forged_response != NULL) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = forged_response;
|
||||
iq->response = forged_response;
|
||||
next_state(iq, FINISHED_STATE);
|
||||
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
|
||||
log_err("rpz: after cached cname, prepend rrsets: out of memory");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
qstate->return_msg->qinfo = qstate->qinfo;
|
||||
return 0;
|
||||
}
|
||||
/* Follow the CNAME response */
|
||||
iq->dp = NULL;
|
||||
iq->refetch_glue = 0;
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen,
|
||||
dpname_storage, sizeof(dpname_storage))) {
|
||||
/* Asked to not query cache. */
|
||||
verbose(VERB_ALGO, "no-cache set, going to the network");
|
||||
qstate->no_cache_lookup = 1;
|
||||
|
@ -1449,39 +1529,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
}
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = slen;
|
||||
if(qstate->env->auth_zones) {
|
||||
/* apply rpz qname triggers after cname */
|
||||
struct dns_msg* forged_response =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
while(forged_response && reply_find_rrset_section_an(
|
||||
forged_response->rep, iq->qchase.qname,
|
||||
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
|
||||
iq->qchase.qclass)) {
|
||||
/* another cname to follow */
|
||||
if(!handle_cname_response(qstate, iq, forged_response,
|
||||
&sname, &slen)) {
|
||||
errinf(qstate, "malloc failure, CNAME info");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = slen;
|
||||
forged_response =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
}
|
||||
if(forged_response != NULL) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = forged_response;
|
||||
iq->response = forged_response;
|
||||
next_state(iq, FINISHED_STATE);
|
||||
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
|
||||
log_err("rpz: after cached cname, prepend rrsets: out of memory");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
qstate->return_msg->qinfo = qstate->qinfo;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* This *is* a query restart, even if it is a cheap
|
||||
* one. */
|
||||
iq->dp = NULL;
|
||||
|
@ -1494,7 +1541,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
}
|
||||
|
||||
/* if from cache, NULL, else insert 'cache IP' len=0 */
|
||||
if(qstate->reply_origin)
|
||||
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
|
||||
|
@ -1555,7 +1601,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
}
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
|
||||
(iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
|
||||
&& can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL))) {
|
||||
&& can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL, NULL, NULL))) {
|
||||
/* remove first label from delname, root goes to hints,
|
||||
* but only to fetch glue, not for qtype=DS. */
|
||||
/* also when prefetching an NS record, fetch it again from
|
||||
|
@ -1584,6 +1630,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
* root priming situation. */
|
||||
if(iq->dp == NULL) {
|
||||
int r;
|
||||
int nolock = 0;
|
||||
/* if under auth zone, no prime needed */
|
||||
if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
|
||||
return error_response(qstate, id,
|
||||
|
@ -1598,11 +1645,12 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
else if(r)
|
||||
return 0; /* stub prime request made */
|
||||
if(forwards_lookup_root(qstate->env->fwds,
|
||||
iq->qchase.qclass)) {
|
||||
iq->qchase.qclass, nolock)) {
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
/* forward zone root, no root prime needed */
|
||||
/* fill in some dp - safety belt */
|
||||
iq->dp = hints_lookup_root(qstate->env->hints,
|
||||
iq->qchase.qclass);
|
||||
iq->dp = hints_find_root(qstate->env->hints,
|
||||
iq->qchase.qclass, nolock);
|
||||
if(!iq->dp) {
|
||||
log_err("internal error: no hints dp");
|
||||
errinf(qstate, "no hints for this class");
|
||||
|
@ -1610,6 +1658,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory in safety belt");
|
||||
errinf(qstate, "malloc failure, in safety belt");
|
||||
|
@ -1649,15 +1698,13 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
|
||||
ie->use_nat64)) {
|
||||
struct delegpt* retdp = NULL;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
|
||||
if(retdp) {
|
||||
int have_dp = 0;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &have_dp, &iq->dp, qstate->region)) {
|
||||
if(have_dp) {
|
||||
verbose(VERB_QUERY, "cache has stub "
|
||||
"or fwd but no addresses, "
|
||||
"fallback to config");
|
||||
iq->dp = delegpt_copy(retdp,
|
||||
qstate->region);
|
||||
if(!iq->dp) {
|
||||
if(have_dp && !iq->dp) {
|
||||
log_err("out of memory in "
|
||||
"stub/fwd fallback");
|
||||
errinf(qstate, "malloc failure, for fallback to config");
|
||||
|
@ -1677,10 +1724,11 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
}
|
||||
if(dname_is_root(iq->dp->name)) {
|
||||
/* use safety belt */
|
||||
int nolock = 0;
|
||||
verbose(VERB_QUERY, "Cache has root NS but "
|
||||
"no addresses. Fallback to the safety belt.");
|
||||
iq->dp = hints_lookup_root(qstate->env->hints,
|
||||
iq->qchase.qclass);
|
||||
iq->dp = hints_find_root(qstate->env->hints,
|
||||
iq->qchase.qclass, nolock);
|
||||
/* note deleg_msg is from previous lookup,
|
||||
* but RD is on, so it is not used */
|
||||
if(!iq->dp) {
|
||||
|
@ -1689,6 +1737,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
LDNS_RCODE_REFUSED);
|
||||
}
|
||||
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(!iq->dp) {
|
||||
log_err("out of memory in safety belt");
|
||||
errinf(qstate, "malloc failure, in safety belt, for root");
|
||||
|
@ -1744,6 +1793,7 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
delnamelen = iq->qchase.qname_len;
|
||||
if(iq->refetch_glue) {
|
||||
struct iter_hints_stub* stub;
|
||||
int nolock = 0;
|
||||
if(!iq->dp) {
|
||||
log_err("internal or malloc fail: no dp for refetch");
|
||||
errinf(qstate, "malloc failure, no delegation info");
|
||||
|
@ -1753,12 +1803,14 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
* this is above stub without stub-first. */
|
||||
stub = hints_lookup_stub(
|
||||
qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
|
||||
iq->dp);
|
||||
iq->dp, nolock);
|
||||
if(!stub || !stub->dp->has_parent_side_NS ||
|
||||
dname_subdomain_c(iq->dp->name, stub->dp->name)) {
|
||||
delname = iq->dp->name;
|
||||
delnamelen = iq->dp->namelen;
|
||||
}
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(stub) { lock_rw_unlock(&qstate->env->hints->lock); }
|
||||
}
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
|
||||
if(!dname_is_root(delname))
|
||||
|
@ -2062,7 +2114,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
log_assert(iq->dp);
|
||||
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass, NULL)) {
|
||||
iq->qchase.qclass, NULL, NULL, NULL)) {
|
||||
/* fail -- no more targets, no more hope of targets, no hope
|
||||
* of a response. */
|
||||
errinf(qstate, "all the configured stub or forward servers failed,");
|
||||
|
@ -2072,21 +2124,24 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
|
||||
struct delegpt* p = hints_lookup_root(qstate->env->hints,
|
||||
iq->qchase.qclass);
|
||||
if(p) {
|
||||
struct delegpt* dp;
|
||||
int nolock = 0;
|
||||
dp = hints_find_root(qstate->env->hints,
|
||||
iq->qchase.qclass, nolock);
|
||||
if(dp) {
|
||||
struct delegpt_addr* a;
|
||||
iq->chase_flags &= ~BIT_RD; /* go to authorities */
|
||||
for(ns = p->nslist; ns; ns=ns->next) {
|
||||
for(ns = dp->nslist; ns; ns=ns->next) {
|
||||
(void)delegpt_add_ns(iq->dp, qstate->region,
|
||||
ns->name, ns->lame, ns->tls_auth_name,
|
||||
ns->port);
|
||||
}
|
||||
for(a = p->target_list; a; a=a->next_target) {
|
||||
for(a = dp->target_list; a; a=a->next_target) {
|
||||
(void)delegpt_add_addr(iq->dp, qstate->region,
|
||||
&a->addr, a->addrlen, a->bogus,
|
||||
a->lame, a->tls_auth_name, -1, NULL);
|
||||
}
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
}
|
||||
iq->dp->has_parent_side_NS = 1;
|
||||
} else if(!iq->dp->has_parent_side_NS) {
|
||||
|
@ -2164,7 +2219,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
|
||||
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
|
||||
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
|
||||
iq->qchase.qclass, NULL)) {
|
||||
iq->qchase.qclass, NULL, NULL, NULL)) {
|
||||
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
|
||||
"because it is also a stub/forward,",
|
||||
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
|
@ -2746,8 +2801,51 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
delegpt_add_unused_targets(iq->dp);
|
||||
|
||||
if(qstate->env->auth_zones) {
|
||||
/* apply rpz triggers at query time */
|
||||
uint8_t* sname = NULL;
|
||||
size_t snamelen = 0;
|
||||
/* apply rpz triggers at query time; nameserver IP and dname */
|
||||
struct dns_msg* forged_response_after_cname;
|
||||
struct dns_msg* forged_response = rpz_callback_from_iterator_module(qstate, iq);
|
||||
int count = 0;
|
||||
while(forged_response && reply_find_rrset_section_an(
|
||||
forged_response->rep, iq->qchase.qname,
|
||||
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
|
||||
iq->qchase.qclass) &&
|
||||
iq->qchase.qtype != LDNS_RR_TYPE_CNAME &&
|
||||
count++ < ie->max_query_restarts) {
|
||||
/* another cname to follow */
|
||||
if(!handle_cname_response(qstate, iq, forged_response,
|
||||
&sname, &snamelen)) {
|
||||
errinf(qstate, "malloc failure, CNAME info");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = snamelen;
|
||||
forged_response_after_cname =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
if(forged_response_after_cname) {
|
||||
forged_response = forged_response_after_cname;
|
||||
} else {
|
||||
/* Follow the CNAME with a query restart */
|
||||
iq->deleg_msg = NULL;
|
||||
iq->dp = NULL;
|
||||
iq->dsns_point = NULL;
|
||||
iq->auth_zone_response = 0;
|
||||
iq->refetch_glue = 0;
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
fptr_ok(fptr_whitelist_modenv_detach_subs(
|
||||
qstate->env->detach_subs));
|
||||
(*qstate->env->detach_subs)(qstate);
|
||||
iq->num_target_queries = 0;
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
}
|
||||
}
|
||||
if(forged_response != NULL) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
|
@ -3082,7 +3180,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
/* DNAME to a subdomain loop; do not recurse */
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
} else if(type == RESPONSE_TYPE_CNAME &&
|
||||
}
|
||||
if(type == RESPONSE_TYPE_CNAME &&
|
||||
iq->qchase.qtype == LDNS_RR_TYPE_CNAME &&
|
||||
iq->minimisation_state == MINIMISE_STATE &&
|
||||
query_dname_compare(iq->qchase.qname, iq->qinfo_out.qname) == 0) {
|
||||
|
@ -3193,6 +3292,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
}
|
||||
return final_state(iq);
|
||||
} else if(type == RESPONSE_TYPE_REFERRAL) {
|
||||
struct delegpt* old_dp = NULL;
|
||||
/* REFERRAL type responses get a reset of the
|
||||
* delegation point, and back to the QUERYTARGETS_STATE. */
|
||||
verbose(VERB_DETAIL, "query response was REFERRAL");
|
||||
|
@ -3244,6 +3344,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
/* Reset the event state, setting the current delegation
|
||||
* point to the referral. */
|
||||
iq->deleg_msg = iq->response;
|
||||
/* Keep current delegation point for label comparison */
|
||||
old_dp = iq->dp;
|
||||
iq->dp = delegpt_from_message(iq->response, qstate->region);
|
||||
if (qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
|
@ -3251,6 +3353,20 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
errinf(qstate, "malloc failure, for delegation point");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(old_dp->namelabs + 1 < iq->dp->namelabs) {
|
||||
/* We got a grandchild delegation (more than one label
|
||||
* difference) than expected. Check for in-between
|
||||
* delegations in the cache and remove them.
|
||||
* They could prove problematic when they expire
|
||||
* and rrset_expired_above() encounters them during
|
||||
* delegation cache lookups. */
|
||||
uint8_t* qname = iq->dp->name;
|
||||
size_t qnamelen = iq->dp->namelen;
|
||||
rrset_cache_remove_above(qstate->env->rrset_cache,
|
||||
&qname, &qnamelen, LDNS_RR_TYPE_NS,
|
||||
iq->qchase.qclass, *qstate->env->now,
|
||||
old_dp->name, old_dp->namelen);
|
||||
}
|
||||
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
|
||||
qstate->region, iq->dp)) {
|
||||
errinf(qstate, "malloc failure, copy extra info into delegation point");
|
||||
|
@ -3341,10 +3457,13 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
/* apply rpz qname triggers after cname */
|
||||
struct dns_msg* forged_response =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
int count = 0;
|
||||
while(forged_response && reply_find_rrset_section_an(
|
||||
forged_response->rep, iq->qchase.qname,
|
||||
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
|
||||
iq->qchase.qclass)) {
|
||||
iq->qchase.qclass) &&
|
||||
iq->qchase.qtype != LDNS_RR_TYPE_CNAME &&
|
||||
count++ < ie->max_query_restarts) {
|
||||
/* another cname to follow */
|
||||
if(!handle_cname_response(qstate, iq, forged_response,
|
||||
&sname, &snamelen)) {
|
||||
|
@ -3926,17 +4045,9 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
!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);
|
||||
iq->response->rep->reason_bogus_str = err_str;
|
||||
}
|
||||
free(err_str);
|
||||
}
|
||||
|
||||
/* we have finished processing this query */
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "util/storage/slabhash.h"
|
||||
#include "util/edns.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
|
||||
int
|
||||
context_finalize(struct ub_ctx* ctx)
|
||||
|
@ -85,6 +87,12 @@ context_finalize(struct ub_ctx* ctx)
|
|||
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
|
||||
ctx->env, &ctx->mods))
|
||||
return UB_INITFAIL;
|
||||
if(!(ctx->env->fwds = forwards_create()) ||
|
||||
!forwards_apply_cfg(ctx->env->fwds, cfg))
|
||||
return UB_INITFAIL;
|
||||
if(!(ctx->env->hints = hints_create()) ||
|
||||
!hints_apply_cfg(ctx->env->hints, cfg))
|
||||
return UB_INITFAIL;
|
||||
if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
|
||||
return UB_INITFAIL;
|
||||
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
#include "services/authzone.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
@ -171,6 +173,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
|
|||
ctx->env->worker = NULL;
|
||||
ctx->env->need_to_validate = 0;
|
||||
modstack_init(&ctx->mods);
|
||||
ctx->env->modstack = &ctx->mods;
|
||||
rbtree_init(&ctx->queries, &context_query_cmp);
|
||||
return ctx;
|
||||
}
|
||||
|
@ -379,6 +382,8 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
|||
config_delete(ctx->env->cfg);
|
||||
edns_known_options_delete(ctx->env);
|
||||
edns_strings_delete(ctx->env->edns_strings);
|
||||
forwards_delete(ctx->env->fwds);
|
||||
hints_delete(ctx->env->hints);
|
||||
auth_zones_delete(ctx->env->auth_zones);
|
||||
free(ctx->env);
|
||||
}
|
||||
|
|
|
@ -70,8 +70,6 @@
|
|||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#ifdef USE_DNSTAP
|
||||
|
@ -100,8 +98,6 @@ libworker_delete_env(struct libworker* w)
|
|||
!w->is_bg || w->is_bg_thread);
|
||||
sldns_buffer_free(w->env->scratch_buffer);
|
||||
regional_destroy(w->env->scratch);
|
||||
forwards_delete(w->env->fwds);
|
||||
hints_delete(w->env->hints);
|
||||
ub_randfree(w->env->rnd);
|
||||
free(w->env);
|
||||
}
|
||||
|
@ -159,30 +155,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
|||
}
|
||||
w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
|
||||
w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
|
||||
w->env->fwds = forwards_create();
|
||||
if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) {
|
||||
forwards_delete(w->env->fwds);
|
||||
w->env->fwds = NULL;
|
||||
}
|
||||
w->env->hints = hints_create();
|
||||
if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
|
||||
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) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
sldns_buffer_free(w->env->scratch_buffer);
|
||||
w->env->scratch_buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
|
||||
!w->env->hints) {
|
||||
if(!w->env->scratch || !w->env->scratch_buffer) {
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -2152,6 +2152,16 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
|
|||
if(az->rpz_first)
|
||||
az->rpz_first->rpz_az_prev = z;
|
||||
az->rpz_first = z;
|
||||
} else if(c->isrpz && z->rpz) {
|
||||
if(!rpz_config(z->rpz, c)) {
|
||||
log_err("Could not change rpz config");
|
||||
if(x) {
|
||||
lock_basic_unlock(&x->lock);
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(c->isrpz) {
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
|
|
52
sbin/unwind/libunbound/services/cache/dns.c
vendored
52
sbin/unwind/libunbound/services/cache/dns.c
vendored
|
@ -193,46 +193,6 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
|||
slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
|
||||
}
|
||||
|
||||
/** see if an rrset is expired above the qname, return upper qname. */
|
||||
static int
|
||||
rrset_expired_above(struct module_env* env, uint8_t** qname, size_t* qnamelen,
|
||||
uint16_t searchtype, uint16_t qclass, time_t now, uint8_t* expiretop,
|
||||
size_t expiretoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
|
||||
while(*qnamelen > 0) {
|
||||
/* look one label higher */
|
||||
lablen = **qname;
|
||||
*qname += lablen + 1;
|
||||
*qnamelen -= lablen + 1;
|
||||
if(*qnamelen <= 0)
|
||||
break;
|
||||
|
||||
/* looks up with a time of 0, to see expired entries */
|
||||
if((rrset = rrset_cache_lookup(env->rrset_cache, *qname,
|
||||
*qnamelen, searchtype, qclass, 0, 0, 0))) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)rrset->entry.data;
|
||||
if(now > data->ttl) {
|
||||
/* it is expired, this is not wanted */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
|
||||
return 1;
|
||||
}
|
||||
/* it is not expired, continue looking */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* do not look above the expiretop. */
|
||||
if(expiretop && *qnamelen == expiretoplen &&
|
||||
query_dname_compare(*qname, expiretop)==0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** find closest NS or DNAME and returns the rrset (locked) */
|
||||
static struct ub_packed_rrset_key*
|
||||
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
|
@ -266,12 +226,12 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
|||
/* check for expiry, but we have to let go of the rrset
|
||||
* for the lock ordering */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
/* the expired_above function always takes off one
|
||||
* label (if qnamelen>0) and returns the final qname
|
||||
* where it searched, so we can continue from there
|
||||
* turning the O N*N search into O N. */
|
||||
if(!rrset_expired_above(env, &qname, &qnamelen,
|
||||
searchtype, qclass, now, expiretop,
|
||||
/* the rrset_cache_expired_above function always takes
|
||||
* off one label (if qnamelen>0) and returns the final
|
||||
* qname where it searched, so we can continue from
|
||||
* there turning the O N*N search into O N. */
|
||||
if(!rrset_cache_expired_above(env->rrset_cache, &qname,
|
||||
&qnamelen, searchtype, qclass, now, expiretop,
|
||||
expiretoplen)) {
|
||||
/* we want to return rrset, but it may be
|
||||
* gone from cache, if so, just loop like
|
||||
|
|
170
sbin/unwind/libunbound/services/cache/infra.c
vendored
170
sbin/unwind/libunbound/services/cache/infra.c
vendored
|
@ -234,6 +234,81 @@ setup_domain_limits(struct infra_cache* infra, struct config_file* cfg)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** find or create element in wait limit netblock tree */
|
||||
static struct wait_limit_netblock_info*
|
||||
wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
|
||||
int cookie)
|
||||
{
|
||||
rbtree_type* tree;
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
struct wait_limit_netblock_info* d;
|
||||
|
||||
if(!netblockstrtoaddr(str, 0, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse wait limit netblock '%s'", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* can we find it? */
|
||||
if(cookie)
|
||||
tree = &infra->wait_limits_cookie_netblock;
|
||||
else
|
||||
tree = &infra->wait_limits_netblock;
|
||||
d = (struct wait_limit_netblock_info*)addr_tree_find(tree, &addr,
|
||||
addrlen, net);
|
||||
if(d)
|
||||
return d;
|
||||
|
||||
/* create it */
|
||||
d = (struct wait_limit_netblock_info*)calloc(1, sizeof(*d));
|
||||
if(!d)
|
||||
return NULL;
|
||||
d->limit = -1;
|
||||
if(!addr_tree_insert(tree, &d->node, &addr, addrlen, net)) {
|
||||
log_err("duplicate element in domainlimit tree");
|
||||
free(d);
|
||||
return NULL;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/** insert wait limit information into lookup tree */
|
||||
static int
|
||||
infra_wait_limit_netblock_insert(struct infra_cache* infra,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
struct wait_limit_netblock_info* d;
|
||||
for(p = cfg->wait_limit_netblock; p; p = p->next) {
|
||||
d = wait_limit_netblock_findcreate(infra, p->str, 0);
|
||||
if(!d)
|
||||
return 0;
|
||||
d->limit = atoi(p->str2);
|
||||
}
|
||||
for(p = cfg->wait_limit_cookie_netblock; p; p = p->next) {
|
||||
d = wait_limit_netblock_findcreate(infra, p->str, 1);
|
||||
if(!d)
|
||||
return 0;
|
||||
d->limit = atoi(p->str2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** setup wait limits tree (0 on failure) */
|
||||
static int
|
||||
setup_wait_limits(struct infra_cache* infra, struct config_file* cfg)
|
||||
{
|
||||
addr_tree_init(&infra->wait_limits_netblock);
|
||||
addr_tree_init(&infra->wait_limits_cookie_netblock);
|
||||
if(!infra_wait_limit_netblock_insert(infra, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(&infra->wait_limits_netblock);
|
||||
addr_tree_init_parents(&infra->wait_limits_cookie_netblock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct infra_cache*
|
||||
infra_create(struct config_file* cfg)
|
||||
{
|
||||
|
@ -267,6 +342,10 @@ infra_create(struct config_file* cfg)
|
|||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
if(!setup_wait_limits(infra, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
|
||||
|
@ -287,6 +366,12 @@ static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
|
|||
}
|
||||
}
|
||||
|
||||
/** delete wait_limit_netblock_info entries */
|
||||
static void wait_limit_netblock_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
free(n);
|
||||
}
|
||||
|
||||
void
|
||||
infra_delete(struct infra_cache* infra)
|
||||
{
|
||||
|
@ -296,6 +381,10 @@ infra_delete(struct infra_cache* infra)
|
|||
slabhash_delete(infra->domain_rates);
|
||||
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
||||
slabhash_delete(infra->client_ip_rates);
|
||||
traverse_postorder(&infra->wait_limits_netblock,
|
||||
wait_limit_netblock_del, NULL);
|
||||
traverse_postorder(&infra->wait_limits_cookie_netblock,
|
||||
wait_limit_netblock_del, NULL);
|
||||
free(infra);
|
||||
}
|
||||
|
||||
|
@ -880,7 +969,8 @@ static void infra_create_ratedata(struct infra_cache* infra,
|
|||
|
||||
/** create rate data item for ip address */
|
||||
static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int mesh_wait)
|
||||
{
|
||||
hashvalue_type h = hash_addr(addr, addrlen, 0);
|
||||
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
|
||||
|
@ -898,6 +988,7 @@ static void infra_ip_create_ratedata(struct infra_cache* infra,
|
|||
k->entry.data = d;
|
||||
d->qps[0] = 1;
|
||||
d->timestamp[0] = timenow;
|
||||
d->mesh_wait = mesh_wait;
|
||||
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
|
||||
}
|
||||
|
||||
|
@ -1121,6 +1212,81 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
|||
}
|
||||
|
||||
/* create */
|
||||
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
|
||||
infra_ip_create_ratedata(infra, addr, addrlen, timenow, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int infra_wait_limit_allowed(struct infra_cache* infra, struct comm_reply* rep,
|
||||
int cookie_valid, struct config_file* cfg)
|
||||
{
|
||||
struct lruhash_entry* entry;
|
||||
if(cfg->wait_limit == 0)
|
||||
return 1;
|
||||
|
||||
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, 0);
|
||||
if(entry) {
|
||||
rbtree_type* tree;
|
||||
struct wait_limit_netblock_info* w;
|
||||
struct rate_data* d = (struct rate_data*)entry->data;
|
||||
int mesh_wait = d->mesh_wait;
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
/* have the wait amount, check how much is allowed */
|
||||
if(cookie_valid)
|
||||
tree = &infra->wait_limits_cookie_netblock;
|
||||
else tree = &infra->wait_limits_netblock;
|
||||
w = (struct wait_limit_netblock_info*)addr_tree_lookup(tree,
|
||||
&rep->client_addr, rep->client_addrlen);
|
||||
if(w) {
|
||||
if(w->limit != -1 && mesh_wait > w->limit)
|
||||
return 0;
|
||||
} else {
|
||||
/* if there is no IP netblock specific information,
|
||||
* use the configured value. */
|
||||
if(mesh_wait > (cookie_valid?cfg->wait_limit_cookie:
|
||||
cfg->wait_limit))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
|
||||
time_t timenow, struct config_file* cfg)
|
||||
{
|
||||
struct lruhash_entry* entry;
|
||||
if(cfg->wait_limit == 0)
|
||||
return;
|
||||
|
||||
/* Find it */
|
||||
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, 1);
|
||||
if(entry) {
|
||||
struct rate_data* d = (struct rate_data*)entry->data;
|
||||
d->mesh_wait++;
|
||||
lock_rw_unlock(&entry->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create it */
|
||||
infra_ip_create_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, timenow, 1);
|
||||
}
|
||||
|
||||
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
struct lruhash_entry* entry;
|
||||
if(cfg->wait_limit == 0)
|
||||
return;
|
||||
|
||||
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, 1);
|
||||
if(entry) {
|
||||
struct rate_data* d = (struct rate_data*)entry->data;
|
||||
if(d->mesh_wait > 0)
|
||||
d->mesh_wait--;
|
||||
lock_rw_unlock(&entry->lock);
|
||||
}
|
||||
}
|
||||
|
|
28
sbin/unwind/libunbound/services/cache/infra.h
vendored
28
sbin/unwind/libunbound/services/cache/infra.h
vendored
|
@ -122,6 +122,10 @@ struct infra_cache {
|
|||
rbtree_type domain_limits;
|
||||
/** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
|
||||
struct slabhash* client_ip_rates;
|
||||
/** tree of addr_tree_node, with wait_limit_netblock_info information */
|
||||
rbtree_type wait_limits_netblock;
|
||||
/** tree of addr_tree_node, with wait_limit_netblock_info information */
|
||||
rbtree_type wait_limits_cookie_netblock;
|
||||
};
|
||||
|
||||
/** ratelimit, unless overridden by domain_limits, 0 is off */
|
||||
|
@ -184,10 +188,22 @@ struct rate_data {
|
|||
/** what the timestamp is of the qps array members, counter is
|
||||
* valid for that timestamp. Usually now and now-1. */
|
||||
time_t timestamp[RATE_WINDOW];
|
||||
/** the number of queries waiting in the mesh */
|
||||
int mesh_wait;
|
||||
};
|
||||
|
||||
#define ip_rate_data rate_data
|
||||
|
||||
/**
|
||||
* Data to store the configuration per netblock for the wait limit
|
||||
*/
|
||||
struct wait_limit_netblock_info {
|
||||
/** The addr tree node, this must be first. */
|
||||
struct addr_tree_node node;
|
||||
/** the limit on the amount */
|
||||
int limit;
|
||||
};
|
||||
|
||||
/** infra host cache default hash lookup size */
|
||||
#define INFRA_HOST_STARTSIZE 32
|
||||
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
||||
|
@ -474,4 +490,16 @@ void ip_rate_delkeyfunc(void* d, void* arg);
|
|||
/* delete data */
|
||||
#define ip_rate_deldatafunc rate_deldatafunc
|
||||
|
||||
/** See if the IP address can have another reply in the wait limit */
|
||||
int infra_wait_limit_allowed(struct infra_cache* infra, struct comm_reply* rep,
|
||||
int cookie_valid, struct config_file* cfg);
|
||||
|
||||
/** Increment number of waiting replies for IP */
|
||||
void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
|
||||
time_t timenow, struct config_file* cfg);
|
||||
|
||||
/** Decrement number of waiting replies for IP */
|
||||
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
|
||||
struct config_file* cfg);
|
||||
|
||||
#endif /* SERVICES_CACHE_INFRA_H */
|
||||
|
|
87
sbin/unwind/libunbound/services/cache/rrset.c
vendored
87
sbin/unwind/libunbound/services/cache/rrset.c
vendored
|
@ -46,6 +46,7 @@
|
|||
#include "util/data/packed_rrset.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/net_help.h"
|
||||
|
@ -127,6 +128,9 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
|
|||
{
|
||||
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
|
||||
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
|
||||
/* o if new data is expired, current data is better */
|
||||
if( newd->ttl < timenow && cached->ttl >= timenow)
|
||||
return 0;
|
||||
/* o store if rrset has been validated
|
||||
* everything better than bogus data
|
||||
* secure is preferred */
|
||||
|
@ -440,6 +444,89 @@ rrset_check_sec_status(struct rrset_cache* r,
|
|||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
void
|
||||
rrset_cache_remove_above(struct rrset_cache* r, uint8_t** qname, size_t*
|
||||
qnamelen, uint16_t searchtype, uint16_t qclass, time_t now, uint8_t*
|
||||
qnametop, size_t qnametoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
|
||||
while(*qnamelen > 0) {
|
||||
/* look one label higher */
|
||||
lablen = **qname;
|
||||
*qname += lablen + 1;
|
||||
*qnamelen -= lablen + 1;
|
||||
if(*qnamelen <= 0)
|
||||
return;
|
||||
|
||||
/* stop at qnametop */
|
||||
if(qnametop && *qnamelen == qnametoplen &&
|
||||
query_dname_compare(*qname, qnametop)==0)
|
||||
return;
|
||||
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
/* looks up with a time of 0, to see expired entries */
|
||||
if((rrset = rrset_cache_lookup(r, *qname,
|
||||
*qnamelen, searchtype, qclass, 0, 0, 0))) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)rrset->entry.data;
|
||||
int expired = (now > data->ttl);
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
if(expired)
|
||||
log_nametypeclass(verbosity, "this "
|
||||
"(grand)parent rrset will be "
|
||||
"removed (expired)",
|
||||
*qname, searchtype, qclass);
|
||||
else log_nametypeclass(verbosity, "this "
|
||||
"(grand)parent rrset will be "
|
||||
"removed",
|
||||
*qname, searchtype, qclass);
|
||||
}
|
||||
}
|
||||
rrset_cache_remove(r, *qname, *qnamelen, searchtype, qclass, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rrset_cache_expired_above(struct rrset_cache* r, uint8_t** qname, size_t*
|
||||
qnamelen, uint16_t searchtype, uint16_t qclass, time_t now, uint8_t*
|
||||
qnametop, size_t qnametoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
|
||||
while(*qnamelen > 0) {
|
||||
/* look one label higher */
|
||||
lablen = **qname;
|
||||
*qname += lablen + 1;
|
||||
*qnamelen -= lablen + 1;
|
||||
if(*qnamelen <= 0)
|
||||
break;
|
||||
|
||||
/* looks up with a time of 0, to see expired entries */
|
||||
if((rrset = rrset_cache_lookup(r, *qname,
|
||||
*qnamelen, searchtype, qclass, 0, 0, 0))) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)rrset->entry.data;
|
||||
if(now > data->ttl) {
|
||||
/* it is expired, this is not wanted */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
|
||||
return 1;
|
||||
}
|
||||
/* it is not expired, continue looking */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* do not look above the qnametop. */
|
||||
if(qnametop && *qnamelen == qnametoplen &&
|
||||
query_dname_compare(*qname, qnametop)==0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
|
||||
uint16_t type, uint16_t dclass, uint32_t flags)
|
||||
{
|
||||
|
|
31
sbin/unwind/libunbound/services/cache/rrset.h
vendored
31
sbin/unwind/libunbound/services/cache/rrset.h
vendored
|
@ -231,6 +231,37 @@ void rrset_update_sec_status(struct rrset_cache* r,
|
|||
void rrset_check_sec_status(struct rrset_cache* r,
|
||||
struct ub_packed_rrset_key* rrset, time_t now);
|
||||
|
||||
/**
|
||||
* Removes rrsets above the qname, returns upper qname.
|
||||
* @param r: the rrset cache.
|
||||
* @param qname: the start qname, also used as the output.
|
||||
* @param qnamelen: length of qname, updated when it returns.
|
||||
* @param searchtype: qtype to search for.
|
||||
* @param qclass: qclass to search for.
|
||||
* @param now: current time.
|
||||
* @param qnametop: the top qname to stop removal (it is not removed).
|
||||
* @param qnametoplen: length of qnametop.
|
||||
*/
|
||||
void rrset_cache_remove_above(struct rrset_cache* r, uint8_t** qname,
|
||||
size_t* qnamelen, uint16_t searchtype, uint16_t qclass, time_t now,
|
||||
uint8_t* qnametop, size_t qnametoplen);
|
||||
|
||||
/**
|
||||
* Sees if an rrset is expired above the qname, returns upper qname.
|
||||
* @param r: the rrset cache.
|
||||
* @param qname: the start qname, also used as the output.
|
||||
* @param qnamelen: length of qname, updated when it returns.
|
||||
* @param searchtype: qtype to search for.
|
||||
* @param qclass: qclass to search for.
|
||||
* @param now: current time.
|
||||
* @param qnametop: the top qname, don't look farther than that.
|
||||
* @param qnametoplen: length of qnametop.
|
||||
* @return true if there is an expired rrset above, false otherwise.
|
||||
*/
|
||||
int rrset_cache_expired_above(struct rrset_cache* r, uint8_t** qname,
|
||||
size_t* qnamelen, uint16_t searchtype, uint16_t qclass, time_t now,
|
||||
uint8_t* qnametop, size_t qnametoplen);
|
||||
|
||||
/**
|
||||
* Remove an rrset from the cache, by name and type and flags
|
||||
* @param r: rrset cache
|
||||
|
|
|
@ -140,9 +140,11 @@ void
|
|||
verbose_print_unbound_socket(struct unbound_socket* ub_sock)
|
||||
{
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
log_info("listing of unbound_socket structure:");
|
||||
verbose_print_addr(ub_sock->addr);
|
||||
log_info("s is: %d, fam is: %s, acl: %s", ub_sock->s,
|
||||
addr_to_str((void*)ub_sock->addr, ub_sock->addrlen, buf,
|
||||
sizeof(buf));
|
||||
log_info("%s s is: %d, fam is: %s, acl: %s", buf, ub_sock->s,
|
||||
ub_sock->fam == AF_INET?"AF_INET":"AF_INET6",
|
||||
ub_sock->acl?"yes":"no");
|
||||
}
|
||||
|
@ -610,7 +612,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
|||
# elif defined(IP_DONTFRAG) && !defined(__APPLE__)
|
||||
/* the IP_DONTFRAG option if defined in the 11.0 OSX headers,
|
||||
* but does not work on that version, so we exclude it */
|
||||
int off = 0;
|
||||
/* a nonzero value disables fragmentation, according to
|
||||
* docs.oracle.com for ip(4). */
|
||||
int off = 1;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
|
||||
&off, (socklen_t)sizeof(off)) < 0) {
|
||||
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
|
||||
|
@ -1047,7 +1051,22 @@ make_sock(int stype, const char* ifname, const char* port,
|
|||
}
|
||||
}
|
||||
|
||||
ub_sock->addr = res;
|
||||
if(!res->ai_addr) {
|
||||
log_err("getaddrinfo returned no address");
|
||||
freeaddrinfo(res);
|
||||
sock_close(s);
|
||||
return -1;
|
||||
}
|
||||
ub_sock->addr = memdup(res->ai_addr, res->ai_addrlen);
|
||||
ub_sock->addrlen = res->ai_addrlen;
|
||||
if(!ub_sock->addr) {
|
||||
log_err("out of memory: allocate listening address");
|
||||
freeaddrinfo(res);
|
||||
sock_close(s);
|
||||
return -1;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
|
||||
ub_sock->s = s;
|
||||
ub_sock->fam = hints->ai_family;
|
||||
ub_sock->acl = NULL;
|
||||
|
@ -1277,8 +1296,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv, snd, reuseport, transparent,
|
||||
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
|
@ -1289,8 +1307,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
/* getting source addr packet info is highly non-portable */
|
||||
if(!set_recvpktinfo(s, hints->ai_family)) {
|
||||
sock_close(s);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1301,8 +1318,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
|
||||
is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1314,8 +1330,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv, snd, reuseport, transparent,
|
||||
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
|
@ -1332,8 +1347,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
listen_type_udpancil:listen_type_udp),
|
||||
is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1356,8 +1370,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
|
||||
freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
if(noip6) {
|
||||
/*log_warn("IPv6 protocol not available");*/
|
||||
|
@ -1369,8 +1382,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1952,8 +1964,7 @@ void listening_ports_free(struct listen_port* list)
|
|||
}
|
||||
/* rc_ports don't have ub_socket */
|
||||
if(list->socket) {
|
||||
if(list->socket->addr)
|
||||
freeaddrinfo(list->socket->addr);
|
||||
free(list->socket->addr);
|
||||
free(list->socket);
|
||||
}
|
||||
free(list);
|
||||
|
|
|
@ -107,11 +107,13 @@ enum listen_type {
|
|||
* socket properties (just like NSD nsd_socket structure definition)
|
||||
*/
|
||||
struct unbound_socket {
|
||||
/** socket-address structure */
|
||||
struct addrinfo* addr;
|
||||
/** the address of the socket */
|
||||
struct sockaddr* addr;
|
||||
/** length of the address */
|
||||
socklen_t addrlen;
|
||||
/** socket descriptor returned by socket() syscall */
|
||||
int s;
|
||||
/** address family (AF_INET/IF_INET6) */
|
||||
/** address family (AF_INET/AF_INET6) */
|
||||
int fam;
|
||||
/** ACL on the socket (listening interface) */
|
||||
struct acl_addr* acl;
|
||||
|
|
|
@ -330,14 +330,16 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass,
|
|||
static struct local_rrset*
|
||||
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
|
||||
{
|
||||
struct local_rrset* p;
|
||||
struct local_rrset* p, *cname = NULL;
|
||||
type = htons(type);
|
||||
for(p = data->rrsets; p; p = p->next) {
|
||||
if(p->rrset->rk.type == type)
|
||||
return p;
|
||||
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
||||
return p;
|
||||
cname = p;
|
||||
}
|
||||
if(alias_ok)
|
||||
return cname;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "services/outbound_list.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/module.h"
|
||||
|
@ -385,7 +386,7 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
|
|||
&mesh_serve_expired_lookup;
|
||||
|
||||
/* In case this timer already popped, start it again */
|
||||
if(!mstate->s.serve_expired_data->timer) {
|
||||
if(!mstate->s.serve_expired_data->timer && timeout != -1) {
|
||||
mstate->s.serve_expired_data->timer = comm_timer_create(
|
||||
mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
|
||||
if(!mstate->s.serve_expired_data->timer)
|
||||
|
@ -415,6 +416,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
if(rep->c->tcp_req_info) {
|
||||
r_buffer = rep->c->tcp_req_info->spool_buffer;
|
||||
}
|
||||
if(!infra_wait_limit_allowed(mesh->env->infra_cache, rep,
|
||||
edns->cookie_valid, mesh->env->cfg)) {
|
||||
verbose(VERB_ALGO, "Too many queries waiting from the IP. "
|
||||
"dropping incoming query.");
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped++;
|
||||
return;
|
||||
}
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
/* does this create a new reply state? */
|
||||
|
@ -511,6 +520,19 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||
goto servfail_mem;
|
||||
}
|
||||
#ifdef USE_CACHEDB
|
||||
if(!timeout && mesh->env->cfg->serve_expired &&
|
||||
!mesh->env->cfg->serve_expired_client_timeout &&
|
||||
(mesh->env->cachedb_enabled &&
|
||||
mesh->env->cfg->cachedb_check_when_serve_expired)) {
|
||||
if(!mesh_serve_expired_init(s, -1)) {
|
||||
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||
goto servfail_mem;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
infra_wait_limit_inc(mesh->env->infra_cache, rep, *mesh->env->now,
|
||||
mesh->env->cfg);
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
|
@ -616,6 +638,18 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_CACHEDB
|
||||
if(!timeout && mesh->env->cfg->serve_expired &&
|
||||
!mesh->env->cfg->serve_expired_client_timeout &&
|
||||
(mesh->env->cachedb_enabled &&
|
||||
mesh->env->cfg->cachedb_check_when_serve_expired)) {
|
||||
if(!mesh_serve_expired_init(s, -1)) {
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
|
@ -930,6 +964,8 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
|||
* takes no time and also it does not do the mesh accounting */
|
||||
mstate->reply_list = NULL;
|
||||
for(; rep; rep=rep->next) {
|
||||
infra_wait_limit_dec(mesh->env->infra_cache,
|
||||
&rep->query_reply, mesh->env->cfg);
|
||||
comm_point_drop_reply(&rep->query_reply);
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
|
@ -1179,7 +1215,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(!rcode && rep && (rep->security == sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
if(!(reason = errinf_to_str_bogus(&m->s)))
|
||||
if(!(reason = errinf_to_str_bogus(&m->s, NULL)))
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
/* send the reply */
|
||||
|
@ -1413,6 +1449,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
comm_point_send_reply(&r->query_reply);
|
||||
m->reply_list = rlist;
|
||||
}
|
||||
infra_wait_limit_dec(m->s.env->infra_cache, &r->query_reply,
|
||||
m->s.env->cfg);
|
||||
/* account */
|
||||
log_assert(m->s.env->mesh->num_reply_addrs > 0);
|
||||
m->s.env->mesh->num_reply_addrs--;
|
||||
|
@ -1436,7 +1474,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
log_reply_info(NO_VERBOSE, &m->s.qinfo,
|
||||
&r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen, duration, 0, r_buffer,
|
||||
(m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr->ai_addr:NULL),
|
||||
(m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr:NULL),
|
||||
r->query_reply.c->type);
|
||||
}
|
||||
}
|
||||
|
@ -1464,12 +1502,32 @@ void mesh_query_done(struct mesh_state* mstate)
|
|||
&& mstate->s.env->cfg->log_servfail
|
||||
&& !mstate->s.env->cfg->val_log_squelch) {
|
||||
char* err = errinf_to_str_servfail(&mstate->s);
|
||||
if(err)
|
||||
log_err("%s", err);
|
||||
free(err);
|
||||
if(err) { log_err("%s", err); }
|
||||
}
|
||||
}
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
struct timeval old;
|
||||
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
||||
if(mstate->s.env->cfg->discard_timeout != 0 &&
|
||||
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
|
||||
mstate->s.env->cfg->discard_timeout) {
|
||||
/* Drop the reply, it is too old */
|
||||
/* briefly set the reply_list to NULL, so that the
|
||||
* tcp req info cleanup routine that calls the mesh
|
||||
* to deregister the meshstate for it is not done
|
||||
* because the list is NULL and also accounting is not
|
||||
* done there, but instead we do that here. */
|
||||
struct mesh_reply* reply_list = mstate->reply_list;
|
||||
verbose(VERB_ALGO, "drop reply, it is older than discard-timeout");
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
mstate->reply_list = NULL;
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
mstate->s.env->mesh->stats_dropped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
tv = r->start_time;
|
||||
|
||||
|
@ -1493,6 +1551,8 @@ void mesh_query_done(struct mesh_state* mstate)
|
|||
* because the list is NULL and also accounting is not
|
||||
* done there, but instead we do that here. */
|
||||
struct mesh_reply* reply_list = mstate->reply_list;
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
mstate->reply_list = NULL;
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
|
@ -2025,6 +2085,8 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
|||
/* delete it, but allocated in m region */
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
infra_wait_limit_dec(mesh->env->infra_cache,
|
||||
&n->query_reply, mesh->env->cfg);
|
||||
|
||||
/* prev = prev; */
|
||||
n = n->next;
|
||||
|
@ -2165,6 +2227,28 @@ mesh_serve_expired_callback(void* arg)
|
|||
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
||||
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
struct timeval old;
|
||||
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
||||
if(mstate->s.env->cfg->discard_timeout != 0 &&
|
||||
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
|
||||
mstate->s.env->cfg->discard_timeout) {
|
||||
/* Drop the reply, it is too old */
|
||||
/* briefly set the reply_list to NULL, so that the
|
||||
* tcp req info cleanup routine that calls the mesh
|
||||
* to deregister the meshstate for it is not done
|
||||
* because the list is NULL and also accounting is not
|
||||
* done there, but instead we do that here. */
|
||||
struct mesh_reply* reply_list = mstate->reply_list;
|
||||
verbose(VERB_ALGO, "drop reply, it is older than discard-timeout");
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
mstate->reply_list = NULL;
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
mstate->s.env->mesh->stats_dropped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
tv = r->start_time;
|
||||
|
||||
|
@ -2192,6 +2276,8 @@ mesh_serve_expired_callback(void* arg)
|
|||
r, r_buffer, prev, prev_buffer);
|
||||
if(r->query_reply.c->tcp_req_info)
|
||||
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
prev = r;
|
||||
prev_buffer = r_buffer;
|
||||
}
|
||||
|
@ -2238,6 +2324,14 @@ mesh_serve_expired_callback(void* arg)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
mesh_respond_serve_expired(struct mesh_state* mstate)
|
||||
{
|
||||
if(!mstate->s.serve_expired_data)
|
||||
mesh_serve_expired_init(mstate, -1);
|
||||
mesh_serve_expired_callback(mstate);
|
||||
}
|
||||
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
{
|
||||
if(mesh->all.count < mesh->max_reply_states)
|
||||
|
|
|
@ -690,4 +690,10 @@ mesh_serve_expired_lookup(struct module_qstate* qstate,
|
|||
*/
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh);
|
||||
|
||||
/**
|
||||
* Give the serve expired responses.
|
||||
* @param mstate: mesh state for query that has serve_expired_data.
|
||||
*/
|
||||
void mesh_respond_serve_expired(struct mesh_state* mstate);
|
||||
|
||||
#endif /* SERVICES_MESH_H */
|
||||
|
|
|
@ -478,6 +478,67 @@ new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
|
|||
return rrset;
|
||||
}
|
||||
|
||||
/** delete the cname override */
|
||||
static void
|
||||
delete_cname_override(struct rpz* r)
|
||||
{
|
||||
if(r->cname_override) {
|
||||
/* The cname override is what is allocated in the region. */
|
||||
regional_free_all(r->region);
|
||||
r->cname_override = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply rpz config elements to the rpz structure, false on failure. */
|
||||
static int
|
||||
rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
|
||||
{
|
||||
if(p->rpz_taglist && p->rpz_taglistlen) {
|
||||
r->taglistlen = p->rpz_taglistlen;
|
||||
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
|
||||
if(!r->taglist) {
|
||||
log_err("malloc failure on RPZ taglist alloc");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(p->rpz_action_override) {
|
||||
r->action_override = rpz_config_to_action(p->rpz_action_override);
|
||||
}
|
||||
else
|
||||
r->action_override = RPZ_NO_OVERRIDE_ACTION;
|
||||
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
uint8_t nm[LDNS_MAX_DOMAINLEN+1];
|
||||
size_t nmlen = sizeof(nm);
|
||||
|
||||
if(!p->rpz_cname) {
|
||||
log_err("rpz: override with cname action found, but no "
|
||||
"rpz-cname-override configured");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
|
||||
log_err("rpz: cannot parse cname override: %s",
|
||||
p->rpz_cname);
|
||||
return 0;
|
||||
}
|
||||
r->cname_override = new_cname_override(r->region, nm, nmlen);
|
||||
if(!r->cname_override) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
r->log = p->rpz_log;
|
||||
r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
|
||||
if(p->rpz_log_name) {
|
||||
if(!(r->log_name = strdup(p->rpz_log_name))) {
|
||||
log_err("malloc failure on RPZ log_name strdup");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct rpz*
|
||||
rpz_create(struct config_auth* p)
|
||||
{
|
||||
|
@ -513,42 +574,8 @@ rpz_create(struct config_auth* p)
|
|||
goto err;
|
||||
}
|
||||
|
||||
r->taglistlen = p->rpz_taglistlen;
|
||||
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
|
||||
if(p->rpz_action_override) {
|
||||
r->action_override = rpz_config_to_action(p->rpz_action_override);
|
||||
}
|
||||
else
|
||||
r->action_override = RPZ_NO_OVERRIDE_ACTION;
|
||||
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
uint8_t nm[LDNS_MAX_DOMAINLEN+1];
|
||||
size_t nmlen = sizeof(nm);
|
||||
|
||||
if(!p->rpz_cname) {
|
||||
log_err("rpz: override with cname action found, but no "
|
||||
"rpz-cname-override configured");
|
||||
if(!rpz_apply_cfg_elements(r, p))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
|
||||
log_err("rpz: cannot parse cname override: %s",
|
||||
p->rpz_cname);
|
||||
goto err;
|
||||
}
|
||||
r->cname_override = new_cname_override(r->region, nm, nmlen);
|
||||
if(!r->cname_override) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
r->log = p->rpz_log;
|
||||
r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
|
||||
if(p->rpz_log_name) {
|
||||
if(!(r->log_name = strdup(p->rpz_log_name))) {
|
||||
log_err("malloc failure on RPZ log_name strdup");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
err:
|
||||
if(r) {
|
||||
|
@ -571,6 +598,32 @@ err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
rpz_config(struct rpz* r, struct config_auth* p)
|
||||
{
|
||||
/* If the zonefile changes, it is read later, after which
|
||||
* rpz_clear and rpz_finish_config is called. */
|
||||
|
||||
/* free taglist, if any */
|
||||
if(r->taglist) {
|
||||
free(r->taglist);
|
||||
r->taglist = NULL;
|
||||
r->taglistlen = 0;
|
||||
}
|
||||
|
||||
/* free logname, if any */
|
||||
if(r->log_name) {
|
||||
free(r->log_name);
|
||||
r->log_name = NULL;
|
||||
}
|
||||
|
||||
delete_cname_override(r);
|
||||
|
||||
if(!rpz_apply_cfg_elements(r, p))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove RPZ zone name from dname
|
||||
* Copy dname to newdname, without the originlen number of trailing bytes
|
||||
|
@ -1191,16 +1244,20 @@ rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint1
|
|||
/** Find entry for RR type in the list of rrsets for the clientip. */
|
||||
static struct local_rrset*
|
||||
rpz_find_synthesized_rrset(uint16_t qtype,
|
||||
struct clientip_synthesized_rr* data)
|
||||
struct clientip_synthesized_rr* data, int alias_ok)
|
||||
{
|
||||
struct local_rrset* cursor = data->data;
|
||||
struct local_rrset* cursor = data->data, *cname = NULL;
|
||||
while( cursor != NULL) {
|
||||
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
|
||||
if(htons(qtype) == packed_rrset->type) {
|
||||
return cursor;
|
||||
}
|
||||
if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
|
||||
cname = cursor;
|
||||
cursor = cursor->next;
|
||||
}
|
||||
if(alias_ok)
|
||||
return cname;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1386,7 +1443,7 @@ static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
|
|||
struct local_rrset* rrset;
|
||||
struct packed_rrset_data* d;
|
||||
size_t index;
|
||||
rrset = rpz_find_synthesized_rrset(rr_type, node);
|
||||
rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
|
||||
if(rrset == NULL)
|
||||
return 0; /* type not found, ignore */
|
||||
d = (struct packed_rrset_data*)rrset->rrset->entry.data;
|
||||
|
@ -1789,7 +1846,7 @@ rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
|
|||
}
|
||||
|
||||
/* check query type / rr type */
|
||||
rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr);
|
||||
rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: unable to find local-data for query");
|
||||
rrset_count = 0;
|
||||
|
@ -1823,6 +1880,28 @@ nodata:
|
|||
rrset_count, rcode, rsoa);
|
||||
}
|
||||
|
||||
/** Apply the cname override action, during worker request callback.
|
||||
* false on failure. */
|
||||
static int
|
||||
rpz_apply_cname_override_action(struct rpz* r,
|
||||
struct query_info* qinfo, struct regional* temp)
|
||||
{
|
||||
if(!r)
|
||||
return 0;
|
||||
qinfo->local_alias = regional_alloc_zero(temp,
|
||||
sizeof(struct local_rrset));
|
||||
if(qinfo->local_alias == NULL)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp);
|
||||
if(qinfo->local_alias->rrset == NULL) {
|
||||
qinfo->local_alias = NULL;
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
|
||||
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** add additional section SOA record to the reply.
|
||||
* Since this gets fed into the normal iterator answer creation, it
|
||||
* gets minimal-responses applied to it, that can remove the additional SOA
|
||||
|
@ -1933,6 +2012,7 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
|||
msg = rpz_dns_msg_new(ms->region);
|
||||
if(msg == NULL) { return NULL; }
|
||||
|
||||
msg->qinfo = *qi;
|
||||
new_reply_info = construct_reply_info_base(ms->region,
|
||||
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
||||
1, /* qd */
|
||||
|
@ -1975,40 +2055,42 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
|||
|
||||
static inline struct dns_msg*
|
||||
rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
|
||||
struct clientip_synthesized_rr* data, struct auth_zone* az)
|
||||
struct query_info* qi, struct clientip_synthesized_rr* data,
|
||||
struct auth_zone* az)
|
||||
{
|
||||
struct query_info* qi = &ms->qinfo;
|
||||
struct local_rrset* rrset;
|
||||
|
||||
rrset = rpz_find_synthesized_rrset(qi->qtype, data);
|
||||
rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
|
||||
}
|
||||
|
||||
/* copy'n'paste from localzone.c */
|
||||
static struct local_rrset*
|
||||
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
|
||||
{
|
||||
struct local_rrset* p;
|
||||
struct local_rrset* p, *cname = NULL;
|
||||
type = htons(type);
|
||||
for(p = data->rrsets; p; p = p->next) {
|
||||
if(p->rrset->rk.type == type)
|
||||
return p;
|
||||
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
||||
return p;
|
||||
cname = p;
|
||||
}
|
||||
if(alias_ok)
|
||||
return cname;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* based on localzone.c:local_data_answer() */
|
||||
static inline struct dns_msg*
|
||||
rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
|
||||
struct local_zone* z, struct matched_delegation_point const* match,
|
||||
struct auth_zone* az)
|
||||
struct query_info* qi, struct local_zone* z,
|
||||
struct matched_delegation_point const* match, struct auth_zone* az)
|
||||
{
|
||||
struct local_data key;
|
||||
struct local_data* ld;
|
||||
|
@ -2029,13 +2111,13 @@ rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
rrset = local_data_find_type(ld, ms->qinfo.qtype, 1);
|
||||
rrset = local_data_find_type(ld, qi->qtype, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
|
||||
}
|
||||
|
||||
/* like local_data_answer for qname triggers after a cname */
|
||||
|
@ -2052,17 +2134,70 @@ rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
|
|||
key.namelabs = dname_count_labels(qinfo->qname);
|
||||
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
|
||||
if(ld == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: qname after cname: name not found");
|
||||
verbose(VERB_ALGO, "rpz: qname: name not found");
|
||||
return NULL;
|
||||
}
|
||||
rrset = local_data_find_type(ld, qinfo->qtype, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: qname after cname: type not found");
|
||||
verbose(VERB_ALGO, "rpz: qname: type not found");
|
||||
return NULL;
|
||||
}
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
|
||||
}
|
||||
|
||||
/** Synthesize a CNAME message for RPZ action override */
|
||||
static struct dns_msg*
|
||||
rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
|
||||
struct query_info* qinfo)
|
||||
{
|
||||
struct dns_msg* msg = NULL;
|
||||
struct reply_info* new_reply_info;
|
||||
struct ub_packed_rrset_key* rp;
|
||||
|
||||
msg = rpz_dns_msg_new(ms->region);
|
||||
if(msg == NULL) { return NULL; }
|
||||
|
||||
msg->qinfo = *qinfo;
|
||||
new_reply_info = construct_reply_info_base(ms->region,
|
||||
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
||||
1, /* qd */
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
0, /* expttl */
|
||||
1, /* an */
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
1, /* total */
|
||||
sec_status_insecure,
|
||||
LDNS_EDE_NONE);
|
||||
if(new_reply_info == NULL) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
new_reply_info->authoritative = 1;
|
||||
|
||||
rp = respip_copy_rrset(r->cname_override, ms->region);
|
||||
if(rp == NULL) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
rp->rk.dname = qinfo->qname;
|
||||
rp->rk.dname_len = qinfo->qname_len;
|
||||
/* this rrset is from the rpz data, or synthesized.
|
||||
* It is not actually from the network, so we flag it with this
|
||||
* flags as a fake RRset. If later the cache is used to look up
|
||||
* rrsets, then the fake ones are not returned (if you look without
|
||||
* the flag). For like CNAME lookups from the iterator or A, AAAA
|
||||
* lookups for nameserver targets, it would use the without flag
|
||||
* actual data. So that the actual network data and fake data
|
||||
* are kept track of separately. */
|
||||
rp->rk.flags |= PACKED_RRSET_RPZ;
|
||||
new_reply_info->rrsets[0] = rp;
|
||||
|
||||
msg->rep = new_reply_info;
|
||||
return msg;
|
||||
}
|
||||
|
||||
static int
|
||||
rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
||||
struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
|
||||
|
@ -2072,17 +2207,8 @@ rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
|||
struct local_data* ld = NULL;
|
||||
int ret = 0;
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset));
|
||||
if(qinfo->local_alias == NULL) {
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override,
|
||||
sizeof(*r->cname_override));
|
||||
if(qinfo->local_alias->rrset == NULL) {
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
|
||||
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
|
||||
if(!rpz_apply_cname_override_action(r, qinfo, temp))
|
||||
return 0;
|
||||
if(r->log) {
|
||||
log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
|
||||
qinfo, repinfo, NULL, r->log_name);
|
||||
|
@ -2134,8 +2260,9 @@ rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate*
|
|||
}
|
||||
|
||||
static struct dns_msg*
|
||||
rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
struct clientip_synthesized_rr* raddr, struct auth_zone* az)
|
||||
rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
struct rpz* r, struct clientip_synthesized_rr* raddr,
|
||||
struct auth_zone* az)
|
||||
{
|
||||
enum rpz_action action = raddr->action;
|
||||
struct dns_msg* ret = NULL;
|
||||
|
@ -2148,16 +2275,16 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
|||
|
||||
if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch(action) {
|
||||
case RPZ_NXDOMAIN_ACTION:
|
||||
ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||
break;
|
||||
case RPZ_NODATA_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
break;
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
|
@ -2166,17 +2293,20 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
|||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
ms->is_drop = 1;
|
||||
break;
|
||||
case RPZ_LOCAL_DATA_ACTION:
|
||||
ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
|
||||
ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
ms->rpz_passthru = 1;
|
||||
break;
|
||||
case RPZ_CNAME_OVERRIDE_ACTION:
|
||||
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
|
||||
rpz_action_to_string(action));
|
||||
|
@ -2194,9 +2324,9 @@ done:
|
|||
}
|
||||
|
||||
static struct dns_msg*
|
||||
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
struct local_zone* z, struct matched_delegation_point const* match,
|
||||
struct auth_zone* az)
|
||||
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
struct rpz* r, struct local_zone* z,
|
||||
struct matched_delegation_point const* match, struct auth_zone* az)
|
||||
{
|
||||
struct dns_msg* ret = NULL;
|
||||
enum rpz_action action = localzone_type_to_rpz_action(z->type);
|
||||
|
@ -2209,10 +2339,10 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
|||
|
||||
switch(action) {
|
||||
case RPZ_NXDOMAIN_ACTION:
|
||||
ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||
break;
|
||||
case RPZ_NODATA_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
break;
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
|
@ -2221,19 +2351,22 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
|||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
ms->is_drop = 1;
|
||||
break;
|
||||
case RPZ_LOCAL_DATA_ACTION:
|
||||
ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
|
||||
ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
ms->rpz_passthru = 1;
|
||||
break;
|
||||
case RPZ_CNAME_OVERRIDE_ACTION:
|
||||
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
|
||||
verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
|
||||
rpz_action_to_string(action));
|
||||
ret = NULL;
|
||||
}
|
||||
|
@ -2324,7 +2457,7 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
|||
|
||||
/* the nsdname has precedence over the nsip triggers */
|
||||
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
|
||||
ms->qinfo.qclass, &match);
|
||||
is->qchase.qclass, &match);
|
||||
if(z != NULL) {
|
||||
lock_rw_unlock(&a->lock);
|
||||
break;
|
||||
|
@ -2347,9 +2480,9 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
|||
if(z) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
return rpz_apply_nsip_trigger(ms, r, raddr, a);
|
||||
return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
|
||||
}
|
||||
return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
|
||||
return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
|
||||
}
|
||||
|
||||
struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
|
@ -2412,10 +2545,10 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
|||
dname_str(is->qchase.qname, nm);
|
||||
dname_str(z->name, zn);
|
||||
if(strcmp(zn, nm) != 0)
|
||||
verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s",
|
||||
verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s",
|
||||
zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||
else
|
||||
verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s",
|
||||
verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s",
|
||||
nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||
}
|
||||
switch(localzone_type_to_rpz_action(lzt)) {
|
||||
|
@ -2444,7 +2577,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
|||
ms->rpz_passthru = 1;
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
|
||||
verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'",
|
||||
rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||
ret = NULL;
|
||||
}
|
||||
|
@ -2472,8 +2605,21 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
|||
az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
|
||||
|
||||
client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
|
||||
if(node != NULL && *r_out &&
|
||||
(*r_out)->action_override != RPZ_NO_OVERRIDE_ACTION) {
|
||||
client_action = (*r_out)->action_override;
|
||||
}
|
||||
if(client_action == RPZ_PASSTHRU_ACTION) {
|
||||
if(*r_out && (*r_out)->log)
|
||||
log_rpz_apply(
|
||||
(node?"clientip":"qname"),
|
||||
((*z_out)?(*z_out)->name:NULL),
|
||||
(node?&node->node:NULL),
|
||||
client_action, qinfo, repinfo, NULL,
|
||||
(*r_out)->log_name);
|
||||
*passthru = 1;
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
|
||||
client_action != RPZ_PASSTHRU_ACTION)) {
|
||||
|
@ -2488,14 +2634,15 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
|||
if(client_action == RPZ_LOCAL_DATA_ACTION) {
|
||||
rpz_apply_clientip_localdata_action(node, env, qinfo,
|
||||
edns, repinfo, buf, temp, *a_out);
|
||||
ret = 1;
|
||||
} else if(client_action == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
if(!rpz_apply_cname_override_action(*r_out, qinfo,
|
||||
temp)) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
if(*r_out && (*r_out)->log)
|
||||
log_rpz_apply(
|
||||
(node?"clientip":"qname"),
|
||||
((*z_out)?(*z_out)->name:NULL),
|
||||
(node?&node->node:NULL),
|
||||
client_action, qinfo, repinfo, NULL,
|
||||
(*r_out)->log_name);
|
||||
local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
|
||||
repinfo, buf, temp, 0 /* no local data used */,
|
||||
rpz_action_to_localzone_type(client_action));
|
||||
|
@ -2503,8 +2650,15 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
|||
LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
|
||||
== LDNS_RCODE_NXDOMAIN)
|
||||
LDNS_RA_CLR(sldns_buffer_begin(buf));
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
if(*r_out && (*r_out)->log)
|
||||
log_rpz_apply(
|
||||
(node?"clientip":"qname"),
|
||||
((*z_out)?(*z_out)->name:NULL),
|
||||
(node?&node->node:NULL),
|
||||
client_action, qinfo, repinfo, NULL,
|
||||
(*r_out)->log_name);
|
||||
goto done;
|
||||
}
|
||||
ret = -1;
|
||||
|
|
|
@ -225,6 +225,14 @@ int rpz_clear(struct rpz* r);
|
|||
*/
|
||||
struct rpz* rpz_create(struct config_auth* p);
|
||||
|
||||
/**
|
||||
* Change config on rpz, after reload.
|
||||
* @param r: the rpz structure.
|
||||
* @param p: the config that was read.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int rpz_config(struct rpz* r, struct config_auth* p);
|
||||
|
||||
/**
|
||||
* String for RPZ action enum
|
||||
* @param a: RPZ action to get string for
|
||||
|
|
|
@ -126,7 +126,8 @@ void view_delete(struct view* v);
|
|||
*/
|
||||
void views_print(struct views* v);
|
||||
|
||||
/* Find a view by name.
|
||||
/**
|
||||
* Find a view by name.
|
||||
* @param vs: views
|
||||
* @param name: name of the view we are looking for
|
||||
* @param write: 1 for obtaining write lock on found view, 0 for read lock
|
||||
|
|
|
@ -174,6 +174,7 @@ config_create(void)
|
|||
cfg->min_ttl = 0;
|
||||
cfg->max_ttl = 3600 * 24;
|
||||
cfg->max_negative_ttl = 3600;
|
||||
cfg->min_negative_ttl = 0;
|
||||
cfg->prefetch = 0;
|
||||
cfg->prefetch_key = 0;
|
||||
cfg->deny_any = 0;
|
||||
|
@ -308,6 +309,11 @@ config_create(void)
|
|||
cfg->minimal_responses = 1;
|
||||
cfg->rrset_roundrobin = 1;
|
||||
cfg->unknown_server_time_limit = 376;
|
||||
cfg->discard_timeout = 1900; /* msec */
|
||||
cfg->wait_limit = 1000;
|
||||
cfg->wait_limit_cookie = 10000;
|
||||
cfg->wait_limit_netblock = NULL;
|
||||
cfg->wait_limit_cookie_netblock = NULL;
|
||||
cfg->max_udp_size = 1232; /* value taken from edns_buffer_size */
|
||||
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
|
||||
goto error_exit;
|
||||
|
@ -384,6 +390,7 @@ config_create(void)
|
|||
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
|
||||
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
|
||||
cfg->cachedb_no_store = 0;
|
||||
cfg->cachedb_check_when_serve_expired = 1;
|
||||
#ifdef USE_REDIS
|
||||
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
|
||||
cfg->redis_server_path = NULL;
|
||||
|
@ -615,6 +622,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||
{ IS_NUMBER_OR_ZERO; cfg->max_ttl = atoi(val); MAX_TTL=(time_t)cfg->max_ttl;}
|
||||
else if(strcmp(opt, "cache-max-negative-ttl:") == 0)
|
||||
{ IS_NUMBER_OR_ZERO; cfg->max_negative_ttl = atoi(val); MAX_NEG_TTL=(time_t)cfg->max_negative_ttl;}
|
||||
else if(strcmp(opt, "cache-min-negative-ttl:") == 0)
|
||||
{ IS_NUMBER_OR_ZERO; cfg->min_negative_ttl = atoi(val); MIN_NEG_TTL=(time_t)cfg->min_negative_ttl;}
|
||||
else if(strcmp(opt, "cache-min-ttl:") == 0)
|
||||
{ IS_NUMBER_OR_ZERO; cfg->min_ttl = atoi(val); MIN_TTL=(time_t)cfg->min_ttl;}
|
||||
else if(strcmp(opt, "infra-cache-min-rtt:") == 0) {
|
||||
|
@ -722,6 +731,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||
else S_YNO("minimal-responses:", minimal_responses)
|
||||
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
|
||||
else S_NUMBER_OR_ZERO("unknown-server-time-limit:", unknown_server_time_limit)
|
||||
else S_NUMBER_OR_ZERO("discard-timeout:", discard_timeout)
|
||||
else S_NUMBER_OR_ZERO("wait-limit:", wait_limit)
|
||||
else S_NUMBER_OR_ZERO("wait-limit-cookie:", wait_limit_cookie)
|
||||
else S_STRLIST("local-data:", local_data)
|
||||
else S_YNO("unblock-lan-zones:", unblock_lan_zones)
|
||||
else S_YNO("insecure-lan-zones:", insecure_lan_zones)
|
||||
|
@ -827,6 +839,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else S_YNO("cachedb-no-store:", cachedb_no_store)
|
||||
else S_YNO("cachedb-check-when-serve-expired:", cachedb_check_when_serve_expired)
|
||||
#endif /* USE_CACHEDB */
|
||||
else if(strcmp(opt, "define-tag:") ==0) {
|
||||
return config_add_tag(cfg, val);
|
||||
|
@ -1065,6 +1078,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
|||
else O_YNO(opt, "deny-any", deny_any)
|
||||
else O_DEC(opt, "cache-max-ttl", max_ttl)
|
||||
else O_DEC(opt, "cache-max-negative-ttl", max_negative_ttl)
|
||||
else O_DEC(opt, "cache-min-negative-ttl", min_negative_ttl)
|
||||
else O_DEC(opt, "cache-min-ttl", min_ttl)
|
||||
else O_DEC(opt, "infra-host-ttl", host_ttl)
|
||||
else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs)
|
||||
|
@ -1201,6 +1215,11 @@ config_get_option(struct config_file* cfg, const char* opt,
|
|||
else O_YNO(opt, "minimal-responses", minimal_responses)
|
||||
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
|
||||
else O_DEC(opt, "unknown-server-time-limit", unknown_server_time_limit)
|
||||
else O_DEC(opt, "discard-timeout", discard_timeout)
|
||||
else O_DEC(opt, "wait-limit", wait_limit)
|
||||
else O_DEC(opt, "wait-limit-cookie", wait_limit_cookie)
|
||||
else O_LS2(opt, "wait-limit-netblock", wait_limit_netblock)
|
||||
else O_LS2(opt, "wait-limit-cookie-netblock", wait_limit_cookie_netblock)
|
||||
#ifdef CLIENT_SUBNET
|
||||
else O_LST(opt, "send-client-subnet", client_subnet)
|
||||
else O_LST(opt, "client-subnet-zone", client_subnet_zone)
|
||||
|
@ -1318,6 +1337,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
|||
else O_STR(opt, "backend", cachedb_backend)
|
||||
else O_STR(opt, "secret-seed", cachedb_secret)
|
||||
else O_YNO(opt, "cachedb-no-store", cachedb_no_store)
|
||||
else O_YNO(opt, "cachedb-check-when-serve-expired", cachedb_check_when_serve_expired)
|
||||
#ifdef USE_REDIS
|
||||
else O_STR(opt, "redis-server-host", redis_server_host)
|
||||
else O_DEC(opt, "redis-server-port", redis_server_port)
|
||||
|
@ -1671,6 +1691,8 @@ config_delete(struct config_file* cfg)
|
|||
config_deltrplstrlist(cfg->interface_tag_actions);
|
||||
config_deltrplstrlist(cfg->interface_tag_datas);
|
||||
config_delstrlist(cfg->control_ifs.first);
|
||||
config_deldblstrlist(cfg->wait_limit_netblock);
|
||||
config_deldblstrlist(cfg->wait_limit_cookie_netblock);
|
||||
free(cfg->server_key_file);
|
||||
free(cfg->server_cert_file);
|
||||
free(cfg->control_key_file);
|
||||
|
@ -1761,6 +1783,10 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
|
|||
#endif
|
||||
if(!mid) {
|
||||
int port = atoi(str);
|
||||
if(port < 0) {
|
||||
log_err("port number is negative: %d", port);
|
||||
return 0;
|
||||
}
|
||||
if(port == 0 && strcmp(str, "0") != 0) {
|
||||
log_err("cannot parse port number '%s'", str);
|
||||
return 0;
|
||||
|
@ -1770,6 +1796,10 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
|
|||
} else {
|
||||
int i, low, high = atoi(mid+1);
|
||||
char buf[16];
|
||||
if(high < 0) {
|
||||
log_err("port number is negative: %d", high);
|
||||
return 0;
|
||||
}
|
||||
if(high == 0 && strcmp(mid+1, "0") != 0) {
|
||||
log_err("cannot parse port number '%s'", mid+1);
|
||||
return 0;
|
||||
|
@ -1782,10 +1812,18 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
|
|||
memcpy(buf, str, (size_t)(mid-str));
|
||||
buf[mid-str] = 0;
|
||||
low = atoi(buf);
|
||||
if(low < 0) {
|
||||
log_err("port number is negative: %d", low);
|
||||
return 0;
|
||||
}
|
||||
if(low == 0 && strcmp(buf, "0") != 0) {
|
||||
log_err("cannot parse port number '%s'", buf);
|
||||
return 0;
|
||||
}
|
||||
if(high > num) {
|
||||
/* Stop very high values from taking a long time. */
|
||||
high = num;
|
||||
}
|
||||
for(i=low; i<=high; i++) {
|
||||
if(i < num)
|
||||
avail[i] = (allow?i:0);
|
||||
|
@ -2310,6 +2348,7 @@ config_apply(struct config_file* config)
|
|||
SERVE_EXPIRED_REPLY_TTL = (time_t)config->serve_expired_reply_ttl;
|
||||
SERVE_ORIGINAL_TTL = config->serve_original_ttl;
|
||||
MAX_NEG_TTL = (time_t)config->max_negative_ttl;
|
||||
MIN_NEG_TTL = (time_t)config->min_negative_ttl;
|
||||
RTT_MIN_TIMEOUT = config->infra_cache_min_rtt;
|
||||
RTT_MAX_TIMEOUT = config->infra_cache_max_rtt;
|
||||
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
|
||||
|
|
|
@ -315,6 +315,8 @@ struct config_file {
|
|||
int min_ttl;
|
||||
/** the number of seconds maximal negative TTL for SOA in auth */
|
||||
int max_negative_ttl;
|
||||
/** the number of seconds minimal negative TTL for SOA in auth */
|
||||
int min_negative_ttl;
|
||||
/** if prefetching of messages should be performed. */
|
||||
int prefetch;
|
||||
/** if prefetching of DNSKEYs should be performed. */
|
||||
|
@ -535,6 +537,21 @@ struct config_file {
|
|||
/* wait time for unknown server in msec */
|
||||
int unknown_server_time_limit;
|
||||
|
||||
/** Wait time to drop recursion replies */
|
||||
int discard_timeout;
|
||||
|
||||
/** Wait limit for number of replies per IP address */
|
||||
int wait_limit;
|
||||
|
||||
/** Wait limit for number of replies per IP address with cookie */
|
||||
int wait_limit_cookie;
|
||||
|
||||
/** wait limit per netblock */
|
||||
struct config_str2list* wait_limit_netblock;
|
||||
|
||||
/** wait limit with cookie per netblock */
|
||||
struct config_str2list* wait_limit_cookie_netblock;
|
||||
|
||||
/* maximum UDP response size */
|
||||
size_t max_udp_size;
|
||||
|
||||
|
@ -705,6 +722,8 @@ struct config_file {
|
|||
char* cachedb_secret;
|
||||
/** cachedb that does not store, but only reads from database, if on */
|
||||
int cachedb_no_store;
|
||||
/** cachedb check before serving serve-expired response */
|
||||
int cachedb_check_when_serve_expired;
|
||||
#ifdef USE_REDIS
|
||||
/** redis server's IP address or host name */
|
||||
char* redis_server_host;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -297,6 +297,7 @@ rrset-cache-size{COLON} { YDVAR(1, VAR_RRSET_CACHE_SIZE) }
|
|||
rrset-cache-slabs{COLON} { YDVAR(1, VAR_RRSET_CACHE_SLABS) }
|
||||
cache-max-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_TTL) }
|
||||
cache-max-negative-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_NEGATIVE_TTL) }
|
||||
cache-min-negative-ttl{COLON} { YDVAR(1, VAR_CACHE_MIN_NEGATIVE_TTL) }
|
||||
cache-min-ttl{COLON} { YDVAR(1, VAR_CACHE_MIN_TTL) }
|
||||
infra-host-ttl{COLON} { YDVAR(1, VAR_INFRA_HOST_TTL) }
|
||||
infra-lame-ttl{COLON} { YDVAR(1, VAR_INFRA_LAME_TTL) }
|
||||
|
@ -463,6 +464,11 @@ domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) }
|
|||
minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) }
|
||||
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
|
||||
unknown-server-time-limit{COLON} { YDVAR(1, VAR_UNKNOWN_SERVER_TIME_LIMIT) }
|
||||
discard-timeout{COLON} { YDVAR(1, VAR_DISCARD_TIMEOUT) }
|
||||
wait-limit{COLON} { YDVAR(1, VAR_WAIT_LIMIT) }
|
||||
wait-limit-cookie{COLON} { YDVAR(1, VAR_WAIT_LIMIT_COOKIE) }
|
||||
wait-limit-netblock{COLON} { YDVAR(1, VAR_WAIT_LIMIT_NETBLOCK) }
|
||||
wait-limit-cookie-netblock{COLON} { YDVAR(1, VAR_WAIT_LIMIT_COOKIE_NETBLOCK) }
|
||||
max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) }
|
||||
dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
|
||||
dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) }
|
||||
|
@ -560,6 +566,7 @@ cachedb{COLON} { YDVAR(0, VAR_CACHEDB) }
|
|||
backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
|
||||
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
|
||||
cachedb-no-store{COLON} { YDVAR(1, VAR_CACHEDB_NO_STORE) }
|
||||
cachedb-check-when-serve-expired{COLON} { YDVAR(1, VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED) }
|
||||
redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
|
||||
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
|
||||
redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }
|
||||
|
|
|
@ -222,129 +222,136 @@
|
|||
#define VAR_CAPS_WHITELIST 478
|
||||
#define VAR_CACHE_MAX_NEGATIVE_TTL 479
|
||||
#define VAR_PERMIT_SMALL_HOLDDOWN 480
|
||||
#define VAR_QNAME_MINIMISATION 481
|
||||
#define VAR_QNAME_MINIMISATION_STRICT 482
|
||||
#define VAR_IP_FREEBIND 483
|
||||
#define VAR_DEFINE_TAG 484
|
||||
#define VAR_LOCAL_ZONE_TAG 485
|
||||
#define VAR_ACCESS_CONTROL_TAG 486
|
||||
#define VAR_LOCAL_ZONE_OVERRIDE 487
|
||||
#define VAR_ACCESS_CONTROL_TAG_ACTION 488
|
||||
#define VAR_ACCESS_CONTROL_TAG_DATA 489
|
||||
#define VAR_VIEW 490
|
||||
#define VAR_ACCESS_CONTROL_VIEW 491
|
||||
#define VAR_VIEW_FIRST 492
|
||||
#define VAR_SERVE_EXPIRED 493
|
||||
#define VAR_SERVE_EXPIRED_TTL 494
|
||||
#define VAR_SERVE_EXPIRED_TTL_RESET 495
|
||||
#define VAR_SERVE_EXPIRED_REPLY_TTL 496
|
||||
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 497
|
||||
#define VAR_EDE_SERVE_EXPIRED 498
|
||||
#define VAR_SERVE_ORIGINAL_TTL 499
|
||||
#define VAR_FAKE_DSA 500
|
||||
#define VAR_FAKE_SHA1 501
|
||||
#define VAR_LOG_IDENTITY 502
|
||||
#define VAR_HIDE_TRUSTANCHOR 503
|
||||
#define VAR_HIDE_HTTP_USER_AGENT 504
|
||||
#define VAR_HTTP_USER_AGENT 505
|
||||
#define VAR_TRUST_ANCHOR_SIGNALING 506
|
||||
#define VAR_AGGRESSIVE_NSEC 507
|
||||
#define VAR_USE_SYSTEMD 508
|
||||
#define VAR_SHM_ENABLE 509
|
||||
#define VAR_SHM_KEY 510
|
||||
#define VAR_ROOT_KEY_SENTINEL 511
|
||||
#define VAR_DNSCRYPT 512
|
||||
#define VAR_DNSCRYPT_ENABLE 513
|
||||
#define VAR_DNSCRYPT_PORT 514
|
||||
#define VAR_DNSCRYPT_PROVIDER 515
|
||||
#define VAR_DNSCRYPT_SECRET_KEY 516
|
||||
#define VAR_DNSCRYPT_PROVIDER_CERT 517
|
||||
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 518
|
||||
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 519
|
||||
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 520
|
||||
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 521
|
||||
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 522
|
||||
#define VAR_PAD_RESPONSES 523
|
||||
#define VAR_PAD_RESPONSES_BLOCK_SIZE 524
|
||||
#define VAR_PAD_QUERIES 525
|
||||
#define VAR_PAD_QUERIES_BLOCK_SIZE 526
|
||||
#define VAR_IPSECMOD_ENABLED 527
|
||||
#define VAR_IPSECMOD_HOOK 528
|
||||
#define VAR_IPSECMOD_IGNORE_BOGUS 529
|
||||
#define VAR_IPSECMOD_MAX_TTL 530
|
||||
#define VAR_IPSECMOD_WHITELIST 531
|
||||
#define VAR_IPSECMOD_STRICT 532
|
||||
#define VAR_CACHEDB 533
|
||||
#define VAR_CACHEDB_BACKEND 534
|
||||
#define VAR_CACHEDB_SECRETSEED 535
|
||||
#define VAR_CACHEDB_REDISHOST 536
|
||||
#define VAR_CACHEDB_REDISPORT 537
|
||||
#define VAR_CACHEDB_REDISTIMEOUT 538
|
||||
#define VAR_CACHEDB_REDISEXPIRERECORDS 539
|
||||
#define VAR_CACHEDB_REDISPATH 540
|
||||
#define VAR_CACHEDB_REDISPASSWORD 541
|
||||
#define VAR_CACHEDB_REDISLOGICALDB 542
|
||||
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 543
|
||||
#define VAR_FOR_UPSTREAM 544
|
||||
#define VAR_AUTH_ZONE 545
|
||||
#define VAR_ZONEFILE 546
|
||||
#define VAR_MASTER 547
|
||||
#define VAR_URL 548
|
||||
#define VAR_FOR_DOWNSTREAM 549
|
||||
#define VAR_FALLBACK_ENABLED 550
|
||||
#define VAR_TLS_ADDITIONAL_PORT 551
|
||||
#define VAR_LOW_RTT 552
|
||||
#define VAR_LOW_RTT_PERMIL 553
|
||||
#define VAR_FAST_SERVER_PERMIL 554
|
||||
#define VAR_FAST_SERVER_NUM 555
|
||||
#define VAR_ALLOW_NOTIFY 556
|
||||
#define VAR_TLS_WIN_CERT 557
|
||||
#define VAR_TCP_CONNECTION_LIMIT 558
|
||||
#define VAR_ANSWER_COOKIE 559
|
||||
#define VAR_COOKIE_SECRET 560
|
||||
#define VAR_IP_RATELIMIT_COOKIE 561
|
||||
#define VAR_FORWARD_NO_CACHE 562
|
||||
#define VAR_STUB_NO_CACHE 563
|
||||
#define VAR_LOG_SERVFAIL 564
|
||||
#define VAR_DENY_ANY 565
|
||||
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 566
|
||||
#define VAR_LOG_TAG_QUERYREPLY 567
|
||||
#define VAR_STREAM_WAIT_SIZE 568
|
||||
#define VAR_TLS_CIPHERS 569
|
||||
#define VAR_TLS_CIPHERSUITES 570
|
||||
#define VAR_TLS_USE_SNI 571
|
||||
#define VAR_IPSET 572
|
||||
#define VAR_IPSET_NAME_V4 573
|
||||
#define VAR_IPSET_NAME_V6 574
|
||||
#define VAR_TLS_SESSION_TICKET_KEYS 575
|
||||
#define VAR_RPZ 576
|
||||
#define VAR_TAGS 577
|
||||
#define VAR_RPZ_ACTION_OVERRIDE 578
|
||||
#define VAR_RPZ_CNAME_OVERRIDE 579
|
||||
#define VAR_RPZ_LOG 580
|
||||
#define VAR_RPZ_LOG_NAME 581
|
||||
#define VAR_DYNLIB 582
|
||||
#define VAR_DYNLIB_FILE 583
|
||||
#define VAR_EDNS_CLIENT_STRING 584
|
||||
#define VAR_EDNS_CLIENT_STRING_OPCODE 585
|
||||
#define VAR_NSID 586
|
||||
#define VAR_ZONEMD_PERMISSIVE_MODE 587
|
||||
#define VAR_ZONEMD_CHECK 588
|
||||
#define VAR_ZONEMD_REJECT_ABSENCE 589
|
||||
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 590
|
||||
#define VAR_INTERFACE_AUTOMATIC_PORTS 591
|
||||
#define VAR_EDE 592
|
||||
#define VAR_INTERFACE_ACTION 593
|
||||
#define VAR_INTERFACE_VIEW 594
|
||||
#define VAR_INTERFACE_TAG 595
|
||||
#define VAR_INTERFACE_TAG_ACTION 596
|
||||
#define VAR_INTERFACE_TAG_DATA 597
|
||||
#define VAR_PROXY_PROTOCOL_PORT 598
|
||||
#define VAR_STATISTICS_INHIBIT_ZERO 599
|
||||
#define VAR_HARDEN_UNKNOWN_ADDITIONAL 600
|
||||
#define VAR_DISABLE_EDNS_DO 601
|
||||
#define VAR_CACHEDB_NO_STORE 602
|
||||
#define VAR_LOG_DESTADDR 603
|
||||
#define VAR_CACHE_MIN_NEGATIVE_TTL 481
|
||||
#define VAR_QNAME_MINIMISATION 482
|
||||
#define VAR_QNAME_MINIMISATION_STRICT 483
|
||||
#define VAR_IP_FREEBIND 484
|
||||
#define VAR_DEFINE_TAG 485
|
||||
#define VAR_LOCAL_ZONE_TAG 486
|
||||
#define VAR_ACCESS_CONTROL_TAG 487
|
||||
#define VAR_LOCAL_ZONE_OVERRIDE 488
|
||||
#define VAR_ACCESS_CONTROL_TAG_ACTION 489
|
||||
#define VAR_ACCESS_CONTROL_TAG_DATA 490
|
||||
#define VAR_VIEW 491
|
||||
#define VAR_ACCESS_CONTROL_VIEW 492
|
||||
#define VAR_VIEW_FIRST 493
|
||||
#define VAR_SERVE_EXPIRED 494
|
||||
#define VAR_SERVE_EXPIRED_TTL 495
|
||||
#define VAR_SERVE_EXPIRED_TTL_RESET 496
|
||||
#define VAR_SERVE_EXPIRED_REPLY_TTL 497
|
||||
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 498
|
||||
#define VAR_EDE_SERVE_EXPIRED 499
|
||||
#define VAR_SERVE_ORIGINAL_TTL 500
|
||||
#define VAR_FAKE_DSA 501
|
||||
#define VAR_FAKE_SHA1 502
|
||||
#define VAR_LOG_IDENTITY 503
|
||||
#define VAR_HIDE_TRUSTANCHOR 504
|
||||
#define VAR_HIDE_HTTP_USER_AGENT 505
|
||||
#define VAR_HTTP_USER_AGENT 506
|
||||
#define VAR_TRUST_ANCHOR_SIGNALING 507
|
||||
#define VAR_AGGRESSIVE_NSEC 508
|
||||
#define VAR_USE_SYSTEMD 509
|
||||
#define VAR_SHM_ENABLE 510
|
||||
#define VAR_SHM_KEY 511
|
||||
#define VAR_ROOT_KEY_SENTINEL 512
|
||||
#define VAR_DNSCRYPT 513
|
||||
#define VAR_DNSCRYPT_ENABLE 514
|
||||
#define VAR_DNSCRYPT_PORT 515
|
||||
#define VAR_DNSCRYPT_PROVIDER 516
|
||||
#define VAR_DNSCRYPT_SECRET_KEY 517
|
||||
#define VAR_DNSCRYPT_PROVIDER_CERT 518
|
||||
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 519
|
||||
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 520
|
||||
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 521
|
||||
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 522
|
||||
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 523
|
||||
#define VAR_PAD_RESPONSES 524
|
||||
#define VAR_PAD_RESPONSES_BLOCK_SIZE 525
|
||||
#define VAR_PAD_QUERIES 526
|
||||
#define VAR_PAD_QUERIES_BLOCK_SIZE 527
|
||||
#define VAR_IPSECMOD_ENABLED 528
|
||||
#define VAR_IPSECMOD_HOOK 529
|
||||
#define VAR_IPSECMOD_IGNORE_BOGUS 530
|
||||
#define VAR_IPSECMOD_MAX_TTL 531
|
||||
#define VAR_IPSECMOD_WHITELIST 532
|
||||
#define VAR_IPSECMOD_STRICT 533
|
||||
#define VAR_CACHEDB 534
|
||||
#define VAR_CACHEDB_BACKEND 535
|
||||
#define VAR_CACHEDB_SECRETSEED 536
|
||||
#define VAR_CACHEDB_REDISHOST 537
|
||||
#define VAR_CACHEDB_REDISPORT 538
|
||||
#define VAR_CACHEDB_REDISTIMEOUT 539
|
||||
#define VAR_CACHEDB_REDISEXPIRERECORDS 540
|
||||
#define VAR_CACHEDB_REDISPATH 541
|
||||
#define VAR_CACHEDB_REDISPASSWORD 542
|
||||
#define VAR_CACHEDB_REDISLOGICALDB 543
|
||||
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 544
|
||||
#define VAR_FOR_UPSTREAM 545
|
||||
#define VAR_AUTH_ZONE 546
|
||||
#define VAR_ZONEFILE 547
|
||||
#define VAR_MASTER 548
|
||||
#define VAR_URL 549
|
||||
#define VAR_FOR_DOWNSTREAM 550
|
||||
#define VAR_FALLBACK_ENABLED 551
|
||||
#define VAR_TLS_ADDITIONAL_PORT 552
|
||||
#define VAR_LOW_RTT 553
|
||||
#define VAR_LOW_RTT_PERMIL 554
|
||||
#define VAR_FAST_SERVER_PERMIL 555
|
||||
#define VAR_FAST_SERVER_NUM 556
|
||||
#define VAR_ALLOW_NOTIFY 557
|
||||
#define VAR_TLS_WIN_CERT 558
|
||||
#define VAR_TCP_CONNECTION_LIMIT 559
|
||||
#define VAR_ANSWER_COOKIE 560
|
||||
#define VAR_COOKIE_SECRET 561
|
||||
#define VAR_IP_RATELIMIT_COOKIE 562
|
||||
#define VAR_FORWARD_NO_CACHE 563
|
||||
#define VAR_STUB_NO_CACHE 564
|
||||
#define VAR_LOG_SERVFAIL 565
|
||||
#define VAR_DENY_ANY 566
|
||||
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 567
|
||||
#define VAR_LOG_TAG_QUERYREPLY 568
|
||||
#define VAR_DISCARD_TIMEOUT 569
|
||||
#define VAR_WAIT_LIMIT 570
|
||||
#define VAR_WAIT_LIMIT_COOKIE 571
|
||||
#define VAR_WAIT_LIMIT_NETBLOCK 572
|
||||
#define VAR_WAIT_LIMIT_COOKIE_NETBLOCK 573
|
||||
#define VAR_STREAM_WAIT_SIZE 574
|
||||
#define VAR_TLS_CIPHERS 575
|
||||
#define VAR_TLS_CIPHERSUITES 576
|
||||
#define VAR_TLS_USE_SNI 577
|
||||
#define VAR_IPSET 578
|
||||
#define VAR_IPSET_NAME_V4 579
|
||||
#define VAR_IPSET_NAME_V6 580
|
||||
#define VAR_TLS_SESSION_TICKET_KEYS 581
|
||||
#define VAR_RPZ 582
|
||||
#define VAR_TAGS 583
|
||||
#define VAR_RPZ_ACTION_OVERRIDE 584
|
||||
#define VAR_RPZ_CNAME_OVERRIDE 585
|
||||
#define VAR_RPZ_LOG 586
|
||||
#define VAR_RPZ_LOG_NAME 587
|
||||
#define VAR_DYNLIB 588
|
||||
#define VAR_DYNLIB_FILE 589
|
||||
#define VAR_EDNS_CLIENT_STRING 590
|
||||
#define VAR_EDNS_CLIENT_STRING_OPCODE 591
|
||||
#define VAR_NSID 592
|
||||
#define VAR_ZONEMD_PERMISSIVE_MODE 593
|
||||
#define VAR_ZONEMD_CHECK 594
|
||||
#define VAR_ZONEMD_REJECT_ABSENCE 595
|
||||
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 596
|
||||
#define VAR_INTERFACE_AUTOMATIC_PORTS 597
|
||||
#define VAR_EDE 598
|
||||
#define VAR_INTERFACE_ACTION 599
|
||||
#define VAR_INTERFACE_VIEW 600
|
||||
#define VAR_INTERFACE_TAG 601
|
||||
#define VAR_INTERFACE_TAG_ACTION 602
|
||||
#define VAR_INTERFACE_TAG_DATA 603
|
||||
#define VAR_PROXY_PROTOCOL_PORT 604
|
||||
#define VAR_STATISTICS_INHIBIT_ZERO 605
|
||||
#define VAR_HARDEN_UNKNOWN_ADDITIONAL 606
|
||||
#define VAR_DISABLE_EDNS_DO 607
|
||||
#define VAR_CACHEDB_NO_STORE 608
|
||||
#define VAR_LOG_DESTADDR 609
|
||||
#define VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED 610
|
||||
#ifndef YYSTYPE_DEFINED
|
||||
#define YYSTYPE_DEFINED
|
||||
typedef union {
|
||||
|
|
|
@ -153,6 +153,7 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_MIN_CLIENT_SUBNET_IPV4 VAR_MIN_CLIENT_SUBNET_IPV6
|
||||
%token VAR_MAX_ECS_TREE_SIZE_IPV4 VAR_MAX_ECS_TREE_SIZE_IPV6
|
||||
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
|
||||
%token VAR_CACHE_MIN_NEGATIVE_TTL
|
||||
%token VAR_QNAME_MINIMISATION VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND
|
||||
%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG
|
||||
%token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION
|
||||
|
@ -188,6 +189,8 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_ANSWER_COOKIE VAR_COOKIE_SECRET VAR_IP_RATELIMIT_COOKIE
|
||||
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
|
||||
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
|
||||
%token VAR_DISCARD_TIMEOUT VAR_WAIT_LIMIT VAR_WAIT_LIMIT_COOKIE
|
||||
%token VAR_WAIT_LIMIT_NETBLOCK VAR_WAIT_LIMIT_COOKIE_NETBLOCK
|
||||
%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES VAR_TLS_USE_SNI
|
||||
%token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
|
||||
%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE
|
||||
|
@ -200,7 +203,7 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
|
||||
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
|
||||
%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE
|
||||
%token VAR_LOG_DESTADDR
|
||||
%token VAR_LOG_DESTADDR VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
|
@ -298,6 +301,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||
server_min_client_subnet_ipv4 | server_min_client_subnet_ipv6 |
|
||||
server_max_ecs_tree_size_ipv4 | server_max_ecs_tree_size_ipv6 |
|
||||
server_caps_whitelist | server_cache_max_negative_ttl |
|
||||
server_cache_min_negative_ttl |
|
||||
server_permit_small_holddown | server_qname_minimisation |
|
||||
server_ip_freebind | server_define_tag | server_local_zone_tag |
|
||||
server_disable_dnssec_lame_check | server_access_control_tag |
|
||||
|
@ -325,6 +329,8 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||
server_fast_server_permil | server_fast_server_num | server_tls_win_cert |
|
||||
server_tcp_connection_limit | server_log_servfail | server_deny_any |
|
||||
server_unknown_server_time_limit | server_log_tag_queryreply |
|
||||
server_discard_timeout | server_wait_limit | server_wait_limit_cookie |
|
||||
server_wait_limit_netblock | server_wait_limit_cookie_netblock |
|
||||
server_stream_wait_size | server_tls_ciphers |
|
||||
server_tls_ciphersuites | server_tls_session_ticket_keys |
|
||||
server_answer_cookie | server_cookie_secret | server_ip_ratelimit_cookie |
|
||||
|
@ -2014,6 +2020,15 @@ server_cache_max_negative_ttl: VAR_CACHE_MAX_NEGATIVE_TTL STRING_ARG
|
|||
free($2);
|
||||
}
|
||||
;
|
||||
server_cache_min_negative_ttl: VAR_CACHE_MIN_NEGATIVE_TTL STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_cache_min_negative_ttl:%s)\n", $2));
|
||||
if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||||
yyerror("number expected");
|
||||
else cfg_parser->cfg->min_negative_ttl = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_cache_min_ttl: VAR_CACHE_MIN_TTL STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_cache_min_ttl:%s)\n", $2));
|
||||
|
@ -2366,6 +2381,57 @@ server_unknown_server_time_limit: VAR_UNKNOWN_SERVER_TIME_LIMIT STRING_ARG
|
|||
free($2);
|
||||
}
|
||||
;
|
||||
server_discard_timeout: VAR_DISCARD_TIMEOUT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_discard_timeout:%s)\n", $2));
|
||||
cfg_parser->cfg->discard_timeout = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_wait_limit: VAR_WAIT_LIMIT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_wait_limit:%s)\n", $2));
|
||||
cfg_parser->cfg->wait_limit = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_wait_limit_cookie: VAR_WAIT_LIMIT_COOKIE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_wait_limit_cookie:%s)\n", $2));
|
||||
cfg_parser->cfg->wait_limit_cookie = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_wait_limit_netblock: VAR_WAIT_LIMIT_NETBLOCK STRING_ARG STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_wait_limit_netblock:%s %s)\n", $2, $3));
|
||||
if(atoi($3) == 0 && strcmp($3, "0") != 0) {
|
||||
yyerror("number expected");
|
||||
free($2);
|
||||
free($3);
|
||||
} else {
|
||||
if(!cfg_str2list_insert(&cfg_parser->cfg->
|
||||
wait_limit_netblock, $2, $3))
|
||||
fatal_exit("out of memory adding "
|
||||
"wait-limit-netblock");
|
||||
}
|
||||
}
|
||||
;
|
||||
server_wait_limit_cookie_netblock: VAR_WAIT_LIMIT_COOKIE_NETBLOCK STRING_ARG STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_wait_limit_cookie_netblock:%s %s)\n", $2, $3));
|
||||
if(atoi($3) == 0 && strcmp($3, "0") != 0) {
|
||||
yyerror("number expected");
|
||||
free($2);
|
||||
free($3);
|
||||
} else {
|
||||
if(!cfg_str2list_insert(&cfg_parser->cfg->
|
||||
wait_limit_cookie_netblock, $2, $3))
|
||||
fatal_exit("out of memory adding "
|
||||
"wait-limit-cookie-netblock");
|
||||
}
|
||||
}
|
||||
;
|
||||
server_max_udp_size: VAR_MAX_UDP_SIZE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_max_udp_size:%s)\n", $2));
|
||||
|
@ -3723,7 +3789,7 @@ 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 |
|
||||
cachedb_no_store | redis_logical_db
|
||||
cachedb_no_store | redis_logical_db | cachedb_check_when_serve_expired
|
||||
;
|
||||
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
|
||||
{
|
||||
|
@ -3762,6 +3828,19 @@ cachedb_no_store: VAR_CACHEDB_NO_STORE STRING_ARG
|
|||
free($2);
|
||||
}
|
||||
;
|
||||
cachedb_check_when_serve_expired: VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED STRING_ARG
|
||||
{
|
||||
#ifdef USE_CACHEDB
|
||||
OUTYY(("P(cachedb_check_when_serve_expired:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->cachedb_check_when_serve_expired = (strcmp($2, "yes")==0);
|
||||
#else
|
||||
OUTYY(("P(Compiled without cachedb, ignoring)\n"));
|
||||
#endif
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG
|
||||
{
|
||||
#if defined(USE_CACHEDB) && defined(USE_REDIS)
|
||||
|
|
|
@ -82,6 +82,8 @@ extern time_t MAX_TTL;
|
|||
extern time_t MIN_TTL;
|
||||
/** Maximum Negative TTL that is allowed */
|
||||
extern time_t MAX_NEG_TTL;
|
||||
/** Minimum Negative TTL that is allowed */
|
||||
extern time_t MIN_NEG_TTL;
|
||||
/** If we serve expired entries and prefetch them */
|
||||
extern int SERVE_EXPIRED;
|
||||
/** Time to serve records after expiration */
|
||||
|
|
|
@ -61,6 +61,8 @@ time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
|
|||
time_t MIN_TTL = 0;
|
||||
/** MAX Negative TTL, for SOA records in authority section */
|
||||
time_t MAX_NEG_TTL = 3600; /* one hour */
|
||||
/** MIN Negative TTL, for SOA records in authority section */
|
||||
time_t MIN_NEG_TTL = 0;
|
||||
/** If we serve expired entries and prefetch them */
|
||||
int SERVE_EXPIRED = 0;
|
||||
/** Time to serve records after expiration */
|
||||
|
@ -223,18 +225,25 @@ rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to,
|
|||
if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) {
|
||||
/* negative response. see if TTL of SOA record larger than the
|
||||
* minimum-ttl in the rdata of the SOA record */
|
||||
if(*rr_ttl > soa_find_minttl(rr))
|
||||
*rr_ttl = soa_find_minttl(rr);
|
||||
}
|
||||
if(!SERVE_ORIGINAL_TTL && (*rr_ttl < MIN_TTL))
|
||||
if(*rr_ttl > soa_find_minttl(rr)) *rr_ttl = soa_find_minttl(rr);
|
||||
if(!SERVE_ORIGINAL_TTL) {
|
||||
/* If MIN_NEG_TTL is configured skip setting MIN_TTL */
|
||||
if(MIN_NEG_TTL <= 0 && *rr_ttl < MIN_TTL) {
|
||||
*rr_ttl = MIN_TTL;
|
||||
if(!SERVE_ORIGINAL_TTL && (*rr_ttl > MAX_TTL))
|
||||
*rr_ttl = MAX_TTL;
|
||||
if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) {
|
||||
/* max neg ttl overrides the min and max ttl of everything
|
||||
* else, it is for a more specific record */
|
||||
if(*rr_ttl > MAX_NEG_TTL)
|
||||
*rr_ttl = MAX_NEG_TTL;
|
||||
}
|
||||
if(*rr_ttl > MAX_TTL) *rr_ttl = MAX_TTL;
|
||||
}
|
||||
/* MAX_NEG_TTL overrides the min and max ttl of everything
|
||||
* else; it is for a more specific record */
|
||||
if(*rr_ttl > MAX_NEG_TTL) *rr_ttl = MAX_NEG_TTL;
|
||||
/* MIN_NEG_TTL overrides the min and max ttl of everything
|
||||
* else if configured; it is for a more specific record */
|
||||
if(MIN_NEG_TTL > 0 && *rr_ttl < MIN_NEG_TTL) {
|
||||
*rr_ttl = MIN_NEG_TTL;
|
||||
}
|
||||
} else if(!SERVE_ORIGINAL_TTL) {
|
||||
if(*rr_ttl < MIN_TTL) *rr_ttl = MIN_TTL;
|
||||
if(*rr_ttl > MAX_TTL) *rr_ttl = MAX_TTL;
|
||||
}
|
||||
if(*rr_ttl < data->ttl)
|
||||
data->ttl = *rr_ttl;
|
||||
|
|
|
@ -129,7 +129,7 @@ void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
|
|||
}
|
||||
}
|
||||
|
||||
char* errinf_to_str_bogus(struct module_qstate* qstate)
|
||||
char* errinf_to_str_bogus(struct module_qstate* qstate, struct regional* region)
|
||||
{
|
||||
char buf[20480];
|
||||
char* p = buf;
|
||||
|
@ -148,6 +148,9 @@ char* errinf_to_str_bogus(struct module_qstate* qstate)
|
|||
snprintf(p, left, " %s", s->str);
|
||||
left -= strlen(p); p += strlen(p);
|
||||
}
|
||||
if(region)
|
||||
p = regional_strdup(region, buf);
|
||||
else
|
||||
p = strdup(buf);
|
||||
if(!p)
|
||||
log_err("malloc failure in errinf_to_str");
|
||||
|
@ -188,7 +191,7 @@ char* errinf_to_str_servfail(struct module_qstate* qstate)
|
|||
snprintf(p, left, " %s", s->str);
|
||||
left -= strlen(p); p += strlen(p);
|
||||
}
|
||||
p = strdup(buf);
|
||||
p = regional_strdup(qstate->region, buf);
|
||||
if(!p)
|
||||
log_err("malloc failure in errinf_to_str");
|
||||
return p;
|
||||
|
@ -206,7 +209,7 @@ char* errinf_to_str_misc(struct module_qstate* qstate)
|
|||
snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str);
|
||||
left -= strlen(p); p += strlen(p);
|
||||
}
|
||||
p = strdup(buf);
|
||||
p = regional_strdup(qstate->region, buf);
|
||||
if(!p)
|
||||
log_err("malloc failure in errinf_to_str");
|
||||
return p;
|
||||
|
|
|
@ -180,6 +180,7 @@ struct iter_hints;
|
|||
struct respip_set;
|
||||
struct respip_client_info;
|
||||
struct respip_addr_info;
|
||||
struct module_stack;
|
||||
|
||||
/** Maximum number of modules in operation */
|
||||
#define MAX_MODULE 16
|
||||
|
@ -511,10 +512,10 @@ struct module_env {
|
|||
/** auth zones */
|
||||
struct auth_zones* auth_zones;
|
||||
/** Mapping of forwarding zones to targets.
|
||||
* iterator forwarder information. per-thread, created by worker */
|
||||
* iterator forwarder information. */
|
||||
struct iter_forwards* fwds;
|
||||
/**
|
||||
* iterator forwarder information. per-thread, created by worker.
|
||||
* iterator stub information.
|
||||
* The hints -- these aren't stored in the cache because they don't
|
||||
* expire. The hints are always used to "prime" the cache. Note
|
||||
* that both root hints and stub zone "hints" are stored in this
|
||||
|
@ -537,6 +538,12 @@ struct module_env {
|
|||
/** EDNS client string information */
|
||||
struct edns_strings* edns_strings;
|
||||
|
||||
/** module stack */
|
||||
struct module_stack* modstack;
|
||||
#ifdef USE_CACHEDB
|
||||
/** the cachedb enabled value, copied and stored here. */
|
||||
int cachedb_enabled;
|
||||
#endif
|
||||
/* Make every mesh state unique, do not aggregate mesh states. */
|
||||
int unique_mesh;
|
||||
};
|
||||
|
@ -824,10 +831,11 @@ void errinf_dname(struct module_qstate* qstate, const char* str,
|
|||
/**
|
||||
* Create error info in string. For validation failures.
|
||||
* @param qstate: query state.
|
||||
* @param region: the region for the result or NULL for malloced result.
|
||||
* @return string or NULL on malloc failure (already logged).
|
||||
* This string is malloced and has to be freed by caller.
|
||||
* This string is malloced if region is NULL and has to be freed by caller.
|
||||
*/
|
||||
char* errinf_to_str_bogus(struct module_qstate* qstate);
|
||||
char* errinf_to_str_bogus(struct module_qstate* qstate, struct regional* region);
|
||||
|
||||
/**
|
||||
* Check the sldns_ede_code of the qstate->errinf.
|
||||
|
@ -840,7 +848,6 @@ sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate);
|
|||
* Create error info in string. For other servfails.
|
||||
* @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_servfail(struct module_qstate* qstate);
|
||||
|
||||
|
@ -848,7 +855,6 @@ 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);
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@
|
|||
|
||||
/** max length of an IP address (the address portion) that we allow */
|
||||
#define MAX_ADDR_STRLEN 128 /* characters */
|
||||
/** max length of a hostname (with port and tls name) that we allow */
|
||||
#define MAX_HOST_STRLEN (LDNS_MAX_DOMAINLEN * 3) /* characters */
|
||||
/** default value for EDNS ADVERTISED size */
|
||||
uint16_t EDNS_ADVERTISED_SIZE = 4096;
|
||||
|
||||
|
@ -486,28 +488,38 @@ uint8_t* authextstrtodname(char* str, int* port, char** auth_name)
|
|||
*port = UNBOUND_DNS_PORT;
|
||||
*auth_name = NULL;
|
||||
if((s=strchr(str, '@'))) {
|
||||
char buf[MAX_HOST_STRLEN];
|
||||
size_t len = (size_t)(s-str);
|
||||
char* hash = strchr(s+1, '#');
|
||||
if(hash) {
|
||||
*auth_name = hash+1;
|
||||
} else {
|
||||
*auth_name = NULL;
|
||||
}
|
||||
if(len >= MAX_HOST_STRLEN) {
|
||||
return NULL;
|
||||
}
|
||||
(void)strlcpy(buf, str, sizeof(buf));
|
||||
buf[len] = 0;
|
||||
*port = atoi(s+1);
|
||||
if(*port == 0) {
|
||||
if(!hash && strcmp(s+1,"0")!=0)
|
||||
return 0;
|
||||
return NULL;
|
||||
if(hash && strncmp(s+1,"0#",2)!=0)
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
*s = 0;
|
||||
dname = sldns_str2wire_dname(str, &dname_len);
|
||||
*s = '@';
|
||||
dname = sldns_str2wire_dname(buf, &dname_len);
|
||||
} else if((s=strchr(str, '#'))) {
|
||||
char buf[MAX_HOST_STRLEN];
|
||||
size_t len = (size_t)(s-str);
|
||||
if(len >= MAX_HOST_STRLEN) {
|
||||
return NULL;
|
||||
}
|
||||
(void)strlcpy(buf, str, sizeof(buf));
|
||||
buf[len] = 0;
|
||||
*port = UNBOUND_DNS_OVER_TLS_PORT;
|
||||
*auth_name = s+1;
|
||||
*s = 0;
|
||||
dname = sldns_str2wire_dname(str, &dname_len);
|
||||
*s = '#';
|
||||
dname = sldns_str2wire_dname(buf, &dname_len);
|
||||
} else {
|
||||
dname = sldns_str2wire_dname(str, &dname_len);
|
||||
}
|
||||
|
@ -1026,11 +1038,11 @@ static void log_crypto_err_io_code_arg(const char* str, int r,
|
|||
} else {
|
||||
if(print_errno) {
|
||||
if(errno == 0)
|
||||
log_err("str: syscall error with errno %s",
|
||||
strerror(errno));
|
||||
else log_err("str: %s", strerror(errno));
|
||||
log_err("%s: syscall error with errno %s",
|
||||
str, strerror(errno));
|
||||
else log_err("%s: %s", str, strerror(errno));
|
||||
} else {
|
||||
log_err("str: %s", inf);
|
||||
log_err("%s: %s", str, inf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4772,9 +4772,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
|||
* sending src (client)/dst (local service) addresses over DNSTAP from udp callback
|
||||
*/
|
||||
if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) {
|
||||
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
|
||||
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
|
||||
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
|
||||
dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->ssl, repinfo->c->buffer);
|
||||
dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, repinfo->c->type, repinfo->c->ssl, repinfo->c->buffer);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
|
@ -4783,9 +4783,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
|||
* sending src (client)/dst (local service) addresses over DNSTAP from TCP callback
|
||||
*/
|
||||
if(repinfo->c->tcp_parent->dtenv != NULL && repinfo->c->tcp_parent->dtenv->log_client_response_messages) {
|
||||
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
|
||||
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
|
||||
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
|
||||
dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->ssl,
|
||||
dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, repinfo->c->type, repinfo->c->ssl,
|
||||
( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer ));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -181,6 +181,8 @@ struct comm_point {
|
|||
/** if the event is added or not */
|
||||
int event_added;
|
||||
|
||||
/** Reference to struct that is part of the listening ports,
|
||||
* where for listening ports information is kept about the address. */
|
||||
struct unbound_socket* socket;
|
||||
|
||||
/** file descriptor for communication point */
|
||||
|
|
|
@ -89,7 +89,7 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy.
|
|||
# if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
|
||||
__BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
(defined(i386) || defined(__i386__) || defined(__i486__) || \
|
||||
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL) || defined(__x86))
|
||||
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL) || defined(__x86) || defined(__loongarch__))
|
||||
# define HASH_LITTLE_ENDIAN 1
|
||||
# define HASH_BIG_ENDIAN 0
|
||||
# elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
|
||||
|
|
|
@ -528,6 +528,40 @@ lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md)
|
|||
lock_quick_unlock(&table->lock);
|
||||
}
|
||||
|
||||
void
|
||||
lruhash_update_space_used(struct lruhash* table, void* cb_arg, int diff_size)
|
||||
{
|
||||
struct lruhash_entry *reclaimlist = NULL;
|
||||
|
||||
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
|
||||
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
|
||||
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
|
||||
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
|
||||
|
||||
if(cb_arg == NULL) cb_arg = table->cb_arg;
|
||||
|
||||
/* update space used */
|
||||
lock_quick_lock(&table->lock);
|
||||
|
||||
if((int)table->space_used + diff_size < 0)
|
||||
table->space_used = 0;
|
||||
else table->space_used = (size_t)((int)table->space_used + diff_size);
|
||||
|
||||
if(table->space_used > table->space_max)
|
||||
reclaim_space(table, &reclaimlist);
|
||||
|
||||
lock_quick_unlock(&table->lock);
|
||||
|
||||
/* finish reclaim if any (outside of critical region) */
|
||||
while(reclaimlist) {
|
||||
struct lruhash_entry* n = reclaimlist->overflow_next;
|
||||
void* d = reclaimlist->data;
|
||||
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
|
||||
(*table->deldatafunc)(d, cb_arg);
|
||||
reclaimlist = n;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lruhash_traverse(struct lruhash* h, int wr,
|
||||
void (*func)(struct lruhash_entry*, void*), void* arg)
|
||||
|
|
|
@ -303,6 +303,17 @@ void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
|
|||
*/
|
||||
void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md);
|
||||
|
||||
/**
|
||||
* Update the size of an element in the hashtable.
|
||||
*
|
||||
* @param table: hash table.
|
||||
* @param cb_override: if not NULL overrides the cb_arg for deletefunc.
|
||||
* @param diff_size: difference in size to the hash table storage.
|
||||
* This is newsize - oldsize, a positive number uses more space.
|
||||
*/
|
||||
void lruhash_update_space_used(struct lruhash* table, void* cb_override,
|
||||
int diff_size);
|
||||
|
||||
/************************* getdns functions ************************/
|
||||
/*** these are used by getdns only and not by unbound. ***/
|
||||
|
||||
|
|
|
@ -166,6 +166,13 @@ int slabhash_is_size(struct slabhash* sl, size_t size, size_t slabs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void slabhash_update_space_used(struct slabhash* sl, hashvalue_type hash,
|
||||
void* cb_arg, int diff_size)
|
||||
{
|
||||
lruhash_update_space_used(sl->array[slab_idx(sl, hash)], cb_arg,
|
||||
diff_size);
|
||||
}
|
||||
|
||||
size_t slabhash_get_mem(struct slabhash* sl)
|
||||
{
|
||||
size_t i, total = sizeof(*sl);
|
||||
|
|
|
@ -161,6 +161,18 @@ size_t slabhash_get_size(struct slabhash* table);
|
|||
*/
|
||||
int slabhash_is_size(struct slabhash* table, size_t size, size_t slabs);
|
||||
|
||||
/**
|
||||
* Update the size of an element in the hashtable, uses
|
||||
* lruhash_update_space_used.
|
||||
*
|
||||
* @param table: hash table.
|
||||
* @param hash: hash value. User calculates the hash.
|
||||
* @param cb_override: if not NULL overrides the cb_arg for deletefunc.
|
||||
* @param diff_size: difference in size to the hash table storage.
|
||||
*/
|
||||
void slabhash_update_space_used(struct slabhash* table, hashvalue_type hash,
|
||||
void* cb_override, int diff_size);
|
||||
|
||||
/**
|
||||
* Retrieve slab hash current memory use.
|
||||
* @param table: hash table.
|
||||
|
|
|
@ -119,6 +119,29 @@ val_classify_response(uint16_t query_flags, struct query_info* origqinf,
|
|||
if(rcode == LDNS_RCODE_NOERROR && qinf->qtype == LDNS_RR_TYPE_ANY)
|
||||
return VAL_CLASS_ANY;
|
||||
|
||||
/* For the query type DNAME, the name matters. Equal name is the
|
||||
* answer looked for, but a subdomain redirects the query. */
|
||||
if(qinf->qtype == LDNS_RR_TYPE_DNAME) {
|
||||
for(i=skip; i<rep->an_numrrsets; i++) {
|
||||
if(rcode == LDNS_RCODE_NOERROR &&
|
||||
ntohs(rep->rrsets[i]->rk.type)
|
||||
== LDNS_RR_TYPE_DNAME &&
|
||||
query_dname_compare(qinf->qname,
|
||||
rep->rrsets[i]->rk.dname) == 0) {
|
||||
/* type is DNAME and name is equal, it is
|
||||
* the answer. For the query name a subdomain
|
||||
* of the rrset.dname it would redirect. */
|
||||
return VAL_CLASS_POSITIVE;
|
||||
}
|
||||
if(ntohs(rep->rrsets[i]->rk.type)
|
||||
== LDNS_RR_TYPE_CNAME)
|
||||
return VAL_CLASS_CNAME;
|
||||
}
|
||||
log_dns_msg("validator: error. failed to classify response message: ",
|
||||
qinf, rep);
|
||||
return VAL_CLASS_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Note that DNAMEs will be ignored here, unless qtype=DNAME. Unless
|
||||
* qtype=CNAME, this will yield a CNAME response. */
|
||||
for(i=skip; i<rep->an_numrrsets; i++) {
|
||||
|
@ -231,6 +254,21 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf,
|
|||
rep->rrsets[i]->rk.dname) == 0) {
|
||||
val_find_rrset_signer(rep->rrsets[i],
|
||||
signer_name, signer_len);
|
||||
/* If there was no signer, and the query
|
||||
* was for type CNAME, and this is a CNAME,
|
||||
* and the previous is a DNAME, then this
|
||||
* is the synthesized CNAME, use the signer
|
||||
* of the DNAME record. */
|
||||
if(*signer_name == NULL &&
|
||||
qinf->qtype == LDNS_RR_TYPE_CNAME &&
|
||||
ntohs(rep->rrsets[i]->rk.type) ==
|
||||
LDNS_RR_TYPE_CNAME && i > skip &&
|
||||
ntohs(rep->rrsets[i-1]->rk.type) ==
|
||||
LDNS_RR_TYPE_DNAME &&
|
||||
dname_strict_subdomain_c(rep->rrsets[i]->rk.dname, rep->rrsets[i-1]->rk.dname)) {
|
||||
val_find_rrset_signer(rep->rrsets[i-1],
|
||||
signer_name, signer_len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -621,7 +621,6 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
* @param vq: validator query state.
|
||||
* @param env: module env for verify.
|
||||
* @param ve: validator env for verify.
|
||||
* @param qchase: query that was made.
|
||||
* @param chase_reply: answer to validate.
|
||||
* @param key_entry: the key entry, which is trusted, and which matches
|
||||
* the signer of the answer. The key entry isgood().
|
||||
|
@ -632,7 +631,7 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
*/
|
||||
static int
|
||||
validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
struct module_env* env, struct val_env* ve, struct query_info* qchase,
|
||||
struct module_env* env, struct val_env* ve,
|
||||
struct reply_info* chase_reply, struct key_entry_key* key_entry,
|
||||
int* suspend)
|
||||
{
|
||||
|
@ -640,7 +639,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
size_t i, slen;
|
||||
struct ub_packed_rrset_key* s;
|
||||
enum sec_status sec;
|
||||
int dname_seen = 0, num_verifies = 0, verified, have_state = 0;
|
||||
int num_verifies = 0, verified, have_state = 0;
|
||||
char* reason = NULL;
|
||||
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
|
||||
*suspend = 0;
|
||||
|
@ -658,9 +657,13 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
/* Skip the CNAME following a (validated) DNAME.
|
||||
* Because of the normalization routines in the iterator,
|
||||
* there will always be an unsigned CNAME following a DNAME
|
||||
* (unless qtype=DNAME). */
|
||||
if(dname_seen && ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) {
|
||||
dname_seen = 0;
|
||||
* (unless qtype=DNAME in the answer part). */
|
||||
if(i>0 && ntohs(chase_reply->rrsets[i-1]->rk.type) ==
|
||||
LDNS_RR_TYPE_DNAME &&
|
||||
ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
|
||||
((struct packed_rrset_data*)chase_reply->rrsets[i-1]->entry.data)->security == sec_status_secure &&
|
||||
dname_strict_subdomain_c(s->rk.dname, chase_reply->rrsets[i-1]->rk.dname)
|
||||
) {
|
||||
/* CNAME was synthesized by our own iterator */
|
||||
/* since the DNAME verified, mark the CNAME as secure */
|
||||
((struct packed_rrset_data*)s->entry.data)->security =
|
||||
|
@ -691,12 +694,6 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Notice a DNAME that should be followed by an unsigned
|
||||
* CNAME. */
|
||||
if(qchase->qtype != LDNS_RR_TYPE_DNAME &&
|
||||
ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME) {
|
||||
dname_seen = 1;
|
||||
}
|
||||
num_verifies += verified;
|
||||
if(num_verifies > MAX_VALIDATE_AT_ONCE &&
|
||||
i+1 < (env->cfg->val_clean_additional?
|
||||
|
@ -2186,7 +2183,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
|
||||
/* check signatures in the message;
|
||||
* answer and authority must be valid, additional is only checked. */
|
||||
if(!validate_msg_signatures(qstate, vq, qstate->env, ve, &vq->qchase,
|
||||
if(!validate_msg_signatures(qstate, vq, qstate->env, ve,
|
||||
vq->chase_reply, vq->key_entry, &suspend)) {
|
||||
if(suspend) {
|
||||
if(!validate_suspend_setup_timer(qstate, vq,
|
||||
|
@ -2456,19 +2453,12 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
log_query_info(NO_VERBOSE, "validation failure",
|
||||
&qstate->qinfo);
|
||||
else {
|
||||
char* err_str = errinf_to_str_bogus(qstate);
|
||||
char* err_str = errinf_to_str_bogus(qstate,
|
||||
qstate->region);
|
||||
if(err_str) {
|
||||
size_t err_str_len = strlen(err_str);
|
||||
log_info("%s", err_str);
|
||||
/* allocate space and store the error
|
||||
* string */
|
||||
vq->orig_msg->rep->reason_bogus_str = regional_alloc(
|
||||
qstate->region,
|
||||
sizeof(char) * (err_str_len+1));
|
||||
memcpy(vq->orig_msg->rep->reason_bogus_str,
|
||||
err_str, err_str_len+1);
|
||||
vq->orig_msg->rep->reason_bogus_str = err_str;
|
||||
}
|
||||
free(err_str);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: conf.c,v 1.47 2023/10/26 14:13:37 jsg Exp $ */
|
||||
/* $OpenBSD: conf.c,v 1.48 2024/06/14 19:49:17 kettenis Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Michael Shalayeff
|
||||
|
@ -47,7 +47,7 @@
|
|||
#include "efipxe.h"
|
||||
#include "softraid_arm64.h"
|
||||
|
||||
const char version[] = "1.18";
|
||||
const char version[] = "1.19";
|
||||
int debug = 0;
|
||||
|
||||
struct fs_ops file_system[] = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: efiboot.c,v 1.50 2024/02/23 21:52:12 kettenis Exp $ */
|
||||
/* $OpenBSD: efiboot.c,v 1.51 2024/06/14 19:49:17 kettenis Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
|
||||
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "efidev.h"
|
||||
#include "efiboot.h"
|
||||
#include "efidt.h"
|
||||
#include "fdt.h"
|
||||
|
||||
EFI_SYSTEM_TABLE *ST;
|
||||
|
@ -67,6 +68,7 @@ static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
|||
static EFI_GUID fdt_guid = FDT_TABLE_GUID;
|
||||
static EFI_GUID smbios_guid = SMBIOS_TABLE_GUID;
|
||||
static EFI_GUID smbios3_guid = SMBIOS3_TABLE_GUID;
|
||||
static EFI_GUID dt_fixup_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
|
||||
|
||||
#define efi_guidcmp(_a, _b) memcmp((_a), (_b), sizeof(EFI_GUID))
|
||||
|
||||
|
@ -1134,12 +1136,18 @@ efi_fdt(void)
|
|||
return fdt_override ? fdt_override : fdt_sys;
|
||||
}
|
||||
|
||||
#define EXTRA_DT_SPACE (32 * 1024)
|
||||
|
||||
int
|
||||
fdt_load_override(char *file)
|
||||
{
|
||||
EFI_DT_FIXUP_PROTOCOL *dt_fixup;
|
||||
EFI_PHYSICAL_ADDRESS addr;
|
||||
char path[MAXPATHLEN];
|
||||
EFI_STATUS status;
|
||||
struct stat sb;
|
||||
size_t dt_size;
|
||||
UINTN sz;
|
||||
int fd;
|
||||
|
||||
if (file == NULL && fdt_override) {
|
||||
|
@ -1157,7 +1165,8 @@ fdt_load_override(char *file)
|
|||
printf("cannot open %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
if (efi_memprobe_find(EFI_SIZE_TO_PAGES(sb.st_size),
|
||||
dt_size = sb.st_size + EXTRA_DT_SPACE;
|
||||
if (efi_memprobe_find(EFI_SIZE_TO_PAGES(dt_size),
|
||||
PAGE_SIZE, EfiLoaderData, &addr) != EFI_SUCCESS) {
|
||||
printf("cannot allocate memory for %s\n", path);
|
||||
return 0;
|
||||
|
@ -1167,9 +1176,18 @@ fdt_load_override(char *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
status = BS->LocateProtocol(&dt_fixup_guid, NULL, (void **)&dt_fixup);
|
||||
if (status == EFI_SUCCESS) {
|
||||
sz = dt_size;
|
||||
status = dt_fixup->Fixup(dt_fixup, (void *)addr, &sz,
|
||||
EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY);
|
||||
if (status != EFI_SUCCESS)
|
||||
panic("DT fixup failed: 0x%lx", status);
|
||||
}
|
||||
|
||||
if (!fdt_init((void *)addr)) {
|
||||
printf("invalid device tree\n");
|
||||
BS->FreePages(addr, EFI_SIZE_TO_PAGES(sb.st_size));
|
||||
BS->FreePages(addr, EFI_SIZE_TO_PAGES(dt_size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1180,7 +1198,7 @@ fdt_load_override(char *file)
|
|||
}
|
||||
|
||||
fdt_override = (void *)addr;
|
||||
fdt_override_size = sb.st_size;
|
||||
fdt_override_size = dt_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
44
sys/arch/arm64/stand/efiboot/efidt.h
Normal file
44
sys/arch/arm64/stand/efiboot/efidt.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* $OpenBSD: efidt.h,v 1.1 2024/06/14 19:49:17 kettenis Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024 Mark Kettenis <kettenis@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <efi.h>
|
||||
#include <efiapi.h>
|
||||
|
||||
#define EFI_DT_FIXUP_PROTOCOL_GUID \
|
||||
{ 0xe617d64c, 0xfe08, 0x46da, \
|
||||
{ 0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00 } }
|
||||
|
||||
INTERFACE_DECL(_EFI_DT_FIXUP_PROTOCOL);
|
||||
|
||||
typedef EFI_STATUS
|
||||
(EFIAPI *EFI_DT_FIXUP) (
|
||||
IN struct _EFI_DT_FIXUP_PROTOCOL *This,
|
||||
IN VOID *Fdt,
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN UINT32 Flags
|
||||
);
|
||||
|
||||
#define EFI_DT_APPLY_FIXUPS 0x00000001
|
||||
#define EFI_DT_RESERVE_MEMORY 0x00000002
|
||||
|
||||
typedef struct _EFI_DT_FIXUP_PROTOCOL {
|
||||
UINT64 Revision;
|
||||
EFI_DT_FIXUP Fixup;
|
||||
} EFI_DT_FIXUP_PROTOCOL;
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ufshci.c,v 1.35 2024/06/09 03:21:54 jsg Exp $ */
|
||||
/* $OpenBSD: ufshci.c,v 1.37 2024/06/14 20:52:07 mglocker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
|
||||
|
@ -68,7 +68,7 @@ void ufshci_dmamem_free(struct ufshci_softc *,
|
|||
struct ufshci_dmamem *);
|
||||
int ufshci_alloc(struct ufshci_softc *);
|
||||
int ufshci_init(struct ufshci_softc *);
|
||||
int ufshci_disable(struct ufshci_softc *);
|
||||
void ufshci_disable(struct ufshci_softc *);
|
||||
int ufshci_doorbell_read(struct ufshci_softc *);
|
||||
void ufshci_doorbell_write(struct ufshci_softc *, int);
|
||||
int ufshci_doorbell_poll(struct ufshci_softc *, int,
|
||||
|
@ -88,7 +88,7 @@ int ufshci_utr_cmd_io(struct ufshci_softc *,
|
|||
int ufshci_utr_cmd_sync(struct ufshci_softc *,
|
||||
struct ufshci_ccb *, struct scsi_xfer *,
|
||||
uint32_t, uint16_t);
|
||||
int ufshci_xfer_complete(struct ufshci_softc *);
|
||||
void ufshci_xfer_complete(struct ufshci_softc *);
|
||||
|
||||
/* SCSI */
|
||||
int ufshci_ccb_alloc(struct ufshci_softc *, int);
|
||||
|
@ -131,7 +131,7 @@ ufshci_intr(void *arg)
|
|||
DPRINTF(3, "%s: status=0x%08x\n", __func__, status);
|
||||
|
||||
if (status == 0)
|
||||
return 0;
|
||||
return handled;
|
||||
|
||||
if (status & UFSHCI_REG_IS_UCCS) {
|
||||
DPRINTF(3, "%s: UCCS interrupt\n", __func__);
|
||||
|
@ -149,11 +149,13 @@ ufshci_intr(void *arg)
|
|||
hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
|
||||
printf("%s: Auto-Hibernate enter error UPMCRS=0x%x\n",
|
||||
__func__, UFSHCI_REG_HCS_UPMCRS(hcs));
|
||||
handled = 1;
|
||||
}
|
||||
if (status & UFSHCI_REG_IS_UHXS) {
|
||||
hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
|
||||
printf("%s: Auto-Hibernate exit error UPMCRS=0x%x\n",
|
||||
__func__, UFSHCI_REG_HCS_UPMCRS(hcs));
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
if (handled == 0) {
|
||||
|
@ -164,7 +166,7 @@ ufshci_intr(void *arg)
|
|||
/* ACK interrupt */
|
||||
UFSHCI_WRITE_4(sc, UFSHCI_REG_IS, status);
|
||||
|
||||
return 1;
|
||||
return handled;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -177,7 +179,8 @@ ufshci_attach(struct ufshci_softc *sc)
|
|||
SIMPLEQ_INIT(&sc->sc_ccb_list);
|
||||
scsi_iopool_init(&sc->sc_iopool, sc, ufshci_ccb_get, ufshci_ccb_put);
|
||||
|
||||
ufshci_reset(sc);
|
||||
if (ufshci_reset(sc))
|
||||
return 1;
|
||||
|
||||
sc->sc_ver = UFSHCI_READ_4(sc, UFSHCI_REG_VER);
|
||||
printf(", UFSHCI %d.%d%d\n",
|
||||
|
@ -240,8 +243,10 @@ ufshci_attach(struct ufshci_softc *sc)
|
|||
sc->sc_flags |= UFSHCI_FLAGS_AGGR_INTR; /* Enable intr. aggregation */
|
||||
#endif
|
||||
/* Allocate the DMA buffers and initialize the controller. */
|
||||
ufshci_alloc(sc);
|
||||
ufshci_init(sc);
|
||||
if (ufshci_alloc(sc))
|
||||
return 1;
|
||||
if (ufshci_init(sc))
|
||||
return 1;
|
||||
|
||||
if (ufshci_ccb_alloc(sc, sc->sc_nutrs) != 0) {
|
||||
printf("%s: %s: Can't allocate CCBs\n",
|
||||
|
@ -294,7 +299,7 @@ ufshci_reset(struct ufshci_softc *sc)
|
|||
if (i == retry) {
|
||||
printf("%s: Enabling Host Controller failed!\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
DPRINTF(2, "\n%s: Host Controller enabled (i=%d)\n", __func__, i);
|
||||
|
@ -318,7 +323,7 @@ ufshci_is_poll(struct ufshci_softc *sc, uint32_t type)
|
|||
}
|
||||
if (i == retry) {
|
||||
printf("%s: %s: timeout\n", sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
DPRINTF(3, "%s: completed after %d retries\n", __func__, i);
|
||||
|
||||
|
@ -394,7 +399,7 @@ ufshci_alloc(struct ufshci_softc *sc)
|
|||
if (sc->sc_dmamem_utmrd == NULL) {
|
||||
printf("%s: Can't allocate DMA memory for UTMRD\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 7.1.1 Host Controller Initialization: 15) */
|
||||
|
@ -403,7 +408,7 @@ ufshci_alloc(struct ufshci_softc *sc)
|
|||
if (sc->sc_dmamem_utrd == NULL) {
|
||||
printf("%s: Can't allocate DMA memory for UTRD\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allocate UCDs. */
|
||||
|
@ -412,7 +417,7 @@ ufshci_alloc(struct ufshci_softc *sc)
|
|||
if (sc->sc_dmamem_ucd == NULL) {
|
||||
printf("%s: Can't allocate DMA memory for UCD\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -442,8 +447,8 @@ ufshci_init(struct ufshci_softc *sc)
|
|||
/* 7.1.1 Host Controller Initialization: 6) */
|
||||
UFSHCI_WRITE_4(sc, UFSHCI_REG_UICCMD,
|
||||
UFSHCI_REG_UICCMD_CMDOP_DME_LINKSTARTUP);
|
||||
if (ufshci_is_poll(sc, UFSHCI_REG_IS_UCCS) != 0)
|
||||
return -1;
|
||||
if (ufshci_is_poll(sc, UFSHCI_REG_IS_UCCS))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* 7.1.1 Host Controller Initialization: 7), 8), 9)
|
||||
|
@ -503,7 +508,7 @@ ufshci_init(struct ufshci_softc *sc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
ufshci_disable(struct ufshci_softc *sc)
|
||||
{
|
||||
/* Stop run queues. */
|
||||
|
@ -512,8 +517,6 @@ ufshci_disable(struct ufshci_softc *sc)
|
|||
|
||||
/* Disable interrupts. */
|
||||
UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -553,7 +556,7 @@ ufshci_doorbell_poll(struct ufshci_softc *sc, int slot, uint32_t timeout_ms)
|
|||
}
|
||||
if (timeout_us == 0) {
|
||||
printf("%s: %s: timeout\n", sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -636,7 +639,7 @@ ufshci_utr_cmd_nop(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||
printf("%s: %s: UTRLRSR not set\n",
|
||||
sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
||||
|
@ -746,7 +749,7 @@ ufshci_utr_cmd_lun(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||
printf("%s: %s: UTRLRSR not set\n",
|
||||
sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
||||
|
@ -854,7 +857,7 @@ ufshci_utr_cmd_inquiry(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||
printf("%s: %s: UTRLRSR not set\n",
|
||||
sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
||||
|
@ -866,7 +869,7 @@ ufshci_utr_cmd_inquiry(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||
ufshci_doorbell_write(sc, slot);
|
||||
|
||||
return slot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -966,7 +969,7 @@ ufshci_utr_cmd_capacity16(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||
printf("%s: %s: UTRLRSR not set\n",
|
||||
sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
||||
|
@ -978,7 +981,7 @@ ufshci_utr_cmd_capacity16(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||
ufshci_doorbell_write(sc, slot);
|
||||
|
||||
return slot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1077,7 +1080,7 @@ ufshci_utr_cmd_capacity(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||
printf("%s: %s: UTRLRSR not set\n",
|
||||
sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
||||
|
@ -1089,7 +1092,7 @@ ufshci_utr_cmd_capacity(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||
ufshci_doorbell_write(sc, slot);
|
||||
|
||||
return slot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1200,7 +1203,7 @@ ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||
printf("%s: %s: UTRLRSR not set\n",
|
||||
sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
||||
|
@ -1212,7 +1215,7 @@ ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||
ufshci_doorbell_write(sc, slot);
|
||||
|
||||
return slot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1302,7 +1305,7 @@ ufshci_utr_cmd_sync(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||
printf("%s: %s: UTRLRSR not set\n",
|
||||
sc->sc_dev.dv_xname, __func__);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
||||
|
@ -1314,10 +1317,10 @@ ufshci_utr_cmd_sync(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
|
|||
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||
ufshci_doorbell_write(sc, slot);
|
||||
|
||||
return slot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
ufshci_xfer_complete(struct ufshci_softc *sc)
|
||||
{
|
||||
struct ufshci_ccb *ccb;
|
||||
|
@ -1374,8 +1377,6 @@ ufshci_xfer_complete(struct ufshci_softc *sc)
|
|||
if (ccb->ccb_status == CCB_STATUS_READY2FREE)
|
||||
ccb->ccb_done(sc, ccb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1589,7 +1590,7 @@ ufshci_scsi_inquiry(struct scsi_xfer *xs)
|
|||
|
||||
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
||||
if (error != 0) {
|
||||
if (error) {
|
||||
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||
goto error1;
|
||||
}
|
||||
|
@ -1602,7 +1603,7 @@ ufshci_scsi_inquiry(struct scsi_xfer *xs)
|
|||
|
||||
/* Response length should be UPIU_SCSI_RSP_INQUIRY_SIZE. */
|
||||
error = ufshci_utr_cmd_inquiry(sc, ccb, xs);
|
||||
if (error == -1)
|
||||
if (error)
|
||||
goto error2;
|
||||
|
||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
||||
|
@ -1644,7 +1645,7 @@ ufshci_scsi_capacity16(struct scsi_xfer *xs)
|
|||
|
||||
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
||||
if (error != 0) {
|
||||
if (error) {
|
||||
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||
goto error1;
|
||||
}
|
||||
|
@ -1657,7 +1658,7 @@ ufshci_scsi_capacity16(struct scsi_xfer *xs)
|
|||
|
||||
/* Response length should be UPIU_SCSI_RSP_CAPACITY16_SIZE. */
|
||||
error = ufshci_utr_cmd_capacity16(sc, ccb, xs);
|
||||
if (error == -1)
|
||||
if (error)
|
||||
goto error2;
|
||||
|
||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
||||
|
@ -1699,7 +1700,7 @@ ufshci_scsi_capacity(struct scsi_xfer *xs)
|
|||
|
||||
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
||||
if (error != 0) {
|
||||
if (error) {
|
||||
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||
goto error1;
|
||||
}
|
||||
|
@ -1712,7 +1713,7 @@ ufshci_scsi_capacity(struct scsi_xfer *xs)
|
|||
|
||||
/* Response length should be UPIU_SCSI_RSP_CAPACITY_SIZE */
|
||||
error = ufshci_utr_cmd_capacity(sc, ccb, xs);
|
||||
if (error == -1)
|
||||
if (error)
|
||||
goto error2;
|
||||
|
||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
||||
|
@ -1757,7 +1758,7 @@ ufshci_scsi_sync(struct scsi_xfer *xs)
|
|||
|
||||
error = ufshci_utr_cmd_sync(sc, ccb, xs, (uint32_t)lba,
|
||||
(uint16_t)blocks);
|
||||
if (error == -1)
|
||||
if (error)
|
||||
goto error;
|
||||
|
||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
||||
|
@ -1797,7 +1798,7 @@ ufshci_scsi_io(struct scsi_xfer *xs, int dir)
|
|||
|
||||
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
||||
if (error != 0) {
|
||||
if (error) {
|
||||
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||
goto error1;
|
||||
}
|
||||
|
@ -1813,7 +1814,7 @@ ufshci_scsi_io(struct scsi_xfer *xs, int dir)
|
|||
error = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_IN);
|
||||
else
|
||||
error = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_OUT);
|
||||
if (error == -1)
|
||||
if (error)
|
||||
goto error2;
|
||||
|
||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ofw_regulator.c,v 1.19 2023/04/15 03:19:43 dlg Exp $ */
|
||||
/* $OpenBSD: ofw_regulator.c,v 1.20 2024/06/14 20:00:32 kettenis Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2016 Mark Kettenis
|
||||
*
|
||||
|
@ -56,6 +56,11 @@ regulator_register(struct regulator_device *rd)
|
|||
rd->rd_ramp_delay =
|
||||
OF_getpropint(rd->rd_node, "regulator-ramp-delay", 0);
|
||||
|
||||
rd->rd_coupled =
|
||||
OF_getpropint(rd->rd_node, "regulator-coupled-with", 0);
|
||||
rd->rd_max_spread =
|
||||
OF_getpropint(rd->rd_node, "regulator-coupled-max-spread", 0);
|
||||
|
||||
if (rd->rd_get_voltage && rd->rd_set_voltage) {
|
||||
uint32_t voltage = rd->rd_get_voltage(rd->rd_cookie);
|
||||
if (voltage < rd->rd_volt_min)
|
||||
|
@ -249,6 +254,10 @@ regulator_set_voltage(uint32_t phandle, uint32_t voltage)
|
|||
if (rd && (voltage < rd->rd_volt_min || voltage > rd->rd_volt_max))
|
||||
return EINVAL;
|
||||
|
||||
/* XXX Coupled regulators are unsupported for now. */
|
||||
if (rd && rd->rd_coupled)
|
||||
return ENOTSUP;
|
||||
|
||||
if (rd && rd->rd_set_voltage) {
|
||||
regulator_do_notify(rd->rd_phandle, voltage);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ofw_regulator.h,v 1.8 2023/04/01 08:37:23 kettenis Exp $ */
|
||||
/* $OpenBSD: ofw_regulator.h,v 1.9 2024/06/14 20:00:32 kettenis Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2016 Mark Kettenis
|
||||
*
|
||||
|
@ -31,6 +31,9 @@ struct regulator_device {
|
|||
uint32_t rd_amp_min, rd_amp_max;
|
||||
uint32_t rd_ramp_delay;
|
||||
|
||||
uint32_t rd_coupled;
|
||||
uint32_t rd_max_spread;
|
||||
|
||||
LIST_ENTRY(regulator_device) rd_list;
|
||||
uint32_t rd_phandle;
|
||||
};
|
||||
|
|
|
@ -812,6 +812,10 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step
|
|||
void __iomem *addr;
|
||||
u32 val;
|
||||
int i;
|
||||
int mmio_bar, mmio_size, mmio_type;
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t memsize;
|
||||
|
||||
/* The caller expects to ver, rel and step to be initialized
|
||||
* here, and there's no good way to check when there was a
|
||||
|
@ -822,9 +826,7 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step
|
|||
*rel = 0;
|
||||
*step = 0;
|
||||
|
||||
STUB();
|
||||
return &no_display;
|
||||
#ifdef notyet
|
||||
#ifdef __linux__
|
||||
addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32));
|
||||
if (!addr) {
|
||||
drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n");
|
||||
|
@ -833,6 +835,19 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step
|
|||
|
||||
val = ioread32(addr);
|
||||
pci_iounmap(pdev, addr);
|
||||
#else
|
||||
mmio_bar = 0x10;
|
||||
mmio_type = pci_mapreg_type(i915->pc, i915->tag, mmio_bar);
|
||||
if (pci_mapreg_map(i915->pa, mmio_bar, mmio_type, 0,
|
||||
&bst, &bsh, NULL, &memsize, 0)) {
|
||||
drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n");
|
||||
return &no_display;
|
||||
}
|
||||
|
||||
val = bus_space_read_4(bst, bsh, i915_mmio_reg_offset(GMD_ID_DISPLAY));
|
||||
|
||||
bus_space_unmap(bst, bsh, memsize);
|
||||
#endif
|
||||
|
||||
if (val == 0) {
|
||||
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
|
||||
|
@ -851,7 +866,6 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step
|
|||
drm_err(&i915->drm, "Unrecognized display IP version %d.%02d; disabling display.\n",
|
||||
*ver, *rel);
|
||||
return &no_display;
|
||||
#endif
|
||||
}
|
||||
|
||||
const struct intel_display_device_info *
|
||||
|
|
|
@ -388,6 +388,27 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915,
|
|||
|
||||
drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = 0x%016llx\n", reg_val);
|
||||
|
||||
/* Wa_14019821291 */
|
||||
if (MEDIA_VER_FULL(i915) == IP_VER(13, 0)) {
|
||||
/*
|
||||
* This workaround is primarily implemented by the BIOS. We
|
||||
* just need to figure out whether the BIOS has applied the
|
||||
* workaround (meaning the programmed address falls within
|
||||
* the DSM) and, if so, reserve that part of the DSM to
|
||||
* prevent accidental reuse. The DSM location should be just
|
||||
* below the WOPCM.
|
||||
*/
|
||||
u64 gscpsmi_base = intel_uncore_read64_2x32(uncore,
|
||||
MTL_GSCPSMI_BASEADDR_LSB,
|
||||
MTL_GSCPSMI_BASEADDR_MSB);
|
||||
if (gscpsmi_base >= i915->dsm.stolen.start &&
|
||||
gscpsmi_base < i915->dsm.stolen.end) {
|
||||
*base = gscpsmi_base;
|
||||
*size = i915->dsm.stolen.end - gscpsmi_base;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) {
|
||||
case GEN8_STOLEN_RESERVED_1M:
|
||||
*size = 1024 * 1024;
|
||||
|
|
|
@ -470,6 +470,9 @@
|
|||
#define XEHP_PSS_MODE2 MCR_REG(0x703c)
|
||||
#define SCOREBOARD_STALL_FLUSH_CONTROL REG_BIT(5)
|
||||
|
||||
#define XEHP_PSS_CHICKEN MCR_REG(0x7044)
|
||||
#define FD_END_COLLECT REG_BIT(5)
|
||||
|
||||
#define GEN7_SC_INSTDONE _MMIO(0x7100)
|
||||
#define GEN12_SC_INSTDONE_EXTRA _MMIO(0x7104)
|
||||
#define GEN12_SC_INSTDONE_EXTRA2 _MMIO(0x7108)
|
||||
|
@ -538,6 +541,9 @@
|
|||
#define XEHP_SQCM MCR_REG(0x8724)
|
||||
#define EN_32B_ACCESS REG_BIT(30)
|
||||
|
||||
#define MTL_GSCPSMI_BASEADDR_LSB _MMIO(0x880c)
|
||||
#define MTL_GSCPSMI_BASEADDR_MSB _MMIO(0x8810)
|
||||
|
||||
#define HSW_IDICR _MMIO(0x9008)
|
||||
#define IDIHASHMSK(x) (((x) & 0x3f) << 16)
|
||||
|
||||
|
@ -1209,6 +1215,7 @@
|
|||
#define GEN12_DISABLE_EARLY_READ REG_BIT(14)
|
||||
#define GEN12_ENABLE_LARGE_GRF_MODE REG_BIT(12)
|
||||
#define GEN12_PUSH_CONST_DEREF_HOLD_DIS REG_BIT(8)
|
||||
#define XELPG_DISABLE_TDL_SVHS_GATING REG_BIT(1)
|
||||
#define GEN12_DISABLE_DOP_GATING REG_BIT(0)
|
||||
|
||||
#define RT_CTRL MCR_REG(0xe530)
|
||||
|
@ -1221,6 +1228,8 @@
|
|||
|
||||
#define XEHP_HDC_CHICKEN0 MCR_REG(0xe5f0)
|
||||
#define LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK REG_GENMASK(13, 11)
|
||||
#define DIS_ATOMIC_CHAINING_TYPED_WRITES REG_BIT(3)
|
||||
|
||||
#define ICL_HDC_MODE MCR_REG(0xe5f4)
|
||||
|
||||
#define EU_PERF_CNTL2 PERF_REG(0xe658)
|
||||
|
|
|
@ -781,6 +781,9 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine,
|
|||
|
||||
/* Wa_18019271663:dg2 */
|
||||
wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE);
|
||||
|
||||
/* Wa_14019877138:dg2 */
|
||||
wa_mcr_masked_en(wal, XEHP_PSS_CHICKEN, FD_END_COLLECT);
|
||||
}
|
||||
|
||||
static void xelpg_ctx_gt_tuning_init(struct intel_engine_cs *engine,
|
||||
|
@ -826,6 +829,9 @@ static void xelpg_ctx_workarounds_init(struct intel_engine_cs *engine,
|
|||
|
||||
/* Wa_18019271663 */
|
||||
wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE);
|
||||
|
||||
/* Wa_14019877138 */
|
||||
wa_mcr_masked_en(wal, XEHP_PSS_CHICKEN, FD_END_COLLECT);
|
||||
}
|
||||
|
||||
static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine,
|
||||
|
@ -2338,6 +2344,14 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
|
|||
LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK);
|
||||
}
|
||||
|
||||
if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) ||
|
||||
IS_DG2(i915)) {
|
||||
/* Wa_14015150844 */
|
||||
wa_mcr_add(wal, XEHP_HDC_CHICKEN0, 0,
|
||||
_MASKED_BIT_ENABLE(DIS_ATOMIC_CHAINING_TYPED_WRITES),
|
||||
0, true);
|
||||
}
|
||||
|
||||
if (IS_DG2_G11(i915) || IS_DG2_G10(i915)) {
|
||||
/* Wa_22014600077:dg2 */
|
||||
wa_mcr_add(wal, GEN10_CACHE_MODE_SS, 0,
|
||||
|
@ -2887,10 +2901,14 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li
|
|||
|
||||
if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_B0, STEP_FOREVER) ||
|
||||
IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER) ||
|
||||
IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 74), IP_VER(12, 74)))
|
||||
IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 74), IP_VER(12, 74))) {
|
||||
/* Wa_14017856879 */
|
||||
wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN3, MTL_DISABLE_FIX_FOR_EOT_FLUSH);
|
||||
|
||||
/* Wa_14020495402 */
|
||||
wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2, XELPG_DISABLE_TDL_SVHS_GATING);
|
||||
}
|
||||
|
||||
if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_A0, STEP_B0) ||
|
||||
IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_A0, STEP_B0))
|
||||
/*
|
||||
|
|
|
@ -2258,6 +2258,7 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
|
|||
int mmio_bar, mmio_size, mmio_type;
|
||||
int ret;
|
||||
|
||||
dev_priv->pa = pa;
|
||||
dev_priv->pc = pa->pa_pc;
|
||||
dev_priv->tag = pa->pa_tag;
|
||||
dev_priv->iot = pa->pa_iot;
|
||||
|
|
|
@ -239,6 +239,7 @@ struct inteldrm_softc {
|
|||
struct i915_dsm dsm;
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
struct pci_attach_args *pa;
|
||||
pci_chipset_tag_t pc;
|
||||
pcitag_t tag;
|
||||
struct extent *memex;
|
||||
|
|
|
@ -290,20 +290,25 @@ static void intel_device_info_subplatform_init(struct drm_i915_private *i915)
|
|||
|
||||
static void ip_ver_read(struct drm_i915_private *i915, u32 offset, struct intel_ip_version *ip)
|
||||
{
|
||||
STUB();
|
||||
#ifdef notyet
|
||||
#ifdef __linux__
|
||||
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
|
||||
void __iomem *addr;
|
||||
#endif
|
||||
u32 val;
|
||||
u8 expected_ver = ip->ver;
|
||||
u8 expected_rel = ip->rel;
|
||||
|
||||
#ifdef __linux__
|
||||
addr = pci_iomap_range(pdev, 0, offset, sizeof(u32));
|
||||
if (drm_WARN_ON(&i915->drm, !addr))
|
||||
return;
|
||||
|
||||
val = ioread32(addr);
|
||||
pci_iounmap(pdev, addr);
|
||||
#else
|
||||
val = bus_space_read_4(i915->vga_regs->bst, i915->vga_regs->bsh,
|
||||
offset);
|
||||
#endif
|
||||
|
||||
ip->ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val);
|
||||
ip->rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val);
|
||||
|
@ -314,7 +319,6 @@ static void ip_ver_read(struct drm_i915_private *i915, u32 offset, struct intel_
|
|||
drm_dbg(&i915->drm,
|
||||
"Hardware reports GMD IP version %u.%u (REG[0x%x] = 0x%08x) but minimum expected is %u.%u\n",
|
||||
ip->ver, ip->rel, offset, val, expected_ver, expected_rel);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: rnd.c,v 1.227 2024/06/04 08:26:11 claudio Exp $ */
|
||||
/* $OpenBSD: rnd.c,v 1.228 2024/06/14 10:17:05 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011,2020 Theo de Raadt.
|
||||
|
@ -172,8 +172,8 @@ const struct filterops randomwrite_filtops = {
|
|||
/*
|
||||
* This function mixes entropy and timing into the entropy input ring.
|
||||
*/
|
||||
void
|
||||
enqueue_randomness(u_int val)
|
||||
static void
|
||||
add_event_data(u_int val)
|
||||
{
|
||||
struct rand_event *rep;
|
||||
int e;
|
||||
|
@ -182,6 +182,12 @@ enqueue_randomness(u_int val)
|
|||
rep = &rnd_event_space[e];
|
||||
rep->re_time += cpu_rnd_messybits();
|
||||
rep->re_val += val;
|
||||
}
|
||||
|
||||
void
|
||||
enqueue_randomness(u_int val)
|
||||
{
|
||||
add_event_data(val);
|
||||
|
||||
if (rnd_cold) {
|
||||
dequeue_randomness(NULL);
|
||||
|
@ -248,9 +254,6 @@ dequeue_randomness(void *v)
|
|||
u_int32_t buf[2];
|
||||
u_int startp, startc, i;
|
||||
|
||||
if (!rnd_cold)
|
||||
timeout_del(&rnd_timeout);
|
||||
|
||||
/* Some very new damage */
|
||||
startp = rnd_event_prod - QEVCONSUME;
|
||||
for (i = 0; i < QEVCONSUME; i++) {
|
||||
|
@ -304,10 +307,8 @@ extract_entropy(u_int8_t *buf)
|
|||
|
||||
/*
|
||||
* Modify pool so next hash will produce different results.
|
||||
* During boot-time enqueue/dequeue stage, avoid recursion.
|
||||
*/
|
||||
if (!rnd_cold)
|
||||
enqueue_randomness(extract_pool[0]);
|
||||
add_event_data(extract_pool[0]);
|
||||
dequeue_randomness(NULL);
|
||||
|
||||
/* Wipe data from memory */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: uipc_socket.c,v 1.335 2024/05/17 19:11:14 mvs Exp $ */
|
||||
/* $OpenBSD: uipc_socket.c,v 1.336 2024/06/14 08:32:22 mvs Exp $ */
|
||||
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -166,6 +166,7 @@ soalloc(const struct protosw *prp, int wait)
|
|||
}
|
||||
break;
|
||||
case AF_KEY:
|
||||
case AF_ROUTE:
|
||||
case AF_UNIX:
|
||||
so->so_snd.sb_flags |= SB_MTXLOCK;
|
||||
so->so_rcv.sb_flags |= SB_MTXLOCK;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: rtsock.c,v 1.373 2023/12/03 10:51:17 mvs Exp $ */
|
||||
/* $OpenBSD: rtsock.c,v 1.374 2024/06/14 08:32:22 mvs Exp $ */
|
||||
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -313,10 +313,12 @@ route_rcvd(struct socket *so)
|
|||
* If we are in a FLUSH state, check if the buffer is
|
||||
* empty so that we can clear the flag.
|
||||
*/
|
||||
|
||||
mtx_enter(&so->so_rcv.sb_mtx);
|
||||
if (((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0) &&
|
||||
((sbspace(rop->rop_socket, &rop->rop_socket->so_rcv) ==
|
||||
rop->rop_socket->so_rcv.sb_hiwat)))
|
||||
((sbspace(so, &so->so_rcv) == so->so_rcv.sb_hiwat)))
|
||||
rop->rop_flags &= ~ROUTECB_FLAG_FLUSH;
|
||||
mtx_leave(&so->so_rcv.sb_mtx);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -478,8 +480,14 @@ rtm_senddesync(struct socket *so)
|
|||
*/
|
||||
desync_mbuf = rtm_msg1(RTM_DESYNC, NULL);
|
||||
if (desync_mbuf != NULL) {
|
||||
if (sbappendaddr(so, &so->so_rcv, &route_src,
|
||||
desync_mbuf, NULL) != 0) {
|
||||
int ret;
|
||||
|
||||
mtx_enter(&so->so_rcv.sb_mtx);
|
||||
ret = sbappendaddr(so, &so->so_rcv, &route_src,
|
||||
desync_mbuf, NULL);
|
||||
mtx_leave(&so->so_rcv.sb_mtx);
|
||||
|
||||
if (ret != 0) {
|
||||
rop->rop_flags &= ~ROUTECB_FLAG_DESYNC;
|
||||
sorwakeup(rop->rop_socket);
|
||||
return;
|
||||
|
@ -586,6 +594,7 @@ rtm_sendup(struct socket *so, struct mbuf *m0)
|
|||
{
|
||||
struct rtpcb *rop = sotortpcb(so);
|
||||
struct mbuf *m;
|
||||
int send_desync = 0;
|
||||
|
||||
soassertlocked(so);
|
||||
|
||||
|
@ -593,8 +602,13 @@ rtm_sendup(struct socket *so, struct mbuf *m0)
|
|||
if (m == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
mtx_enter(&so->so_rcv.sb_mtx);
|
||||
if (sbspace(so, &so->so_rcv) < (2 * MSIZE) ||
|
||||
sbappendaddr(so, &so->so_rcv, &route_src, m, NULL) == 0) {
|
||||
sbappendaddr(so, &so->so_rcv, &route_src, m, NULL) == 0)
|
||||
send_desync = 1;
|
||||
mtx_leave(&so->so_rcv.sb_mtx);
|
||||
|
||||
if (send_desync) {
|
||||
/* Flag socket as desync'ed and flush required */
|
||||
rop->rop_flags |= ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH;
|
||||
rtm_senddesync(so);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: tags.c,v 1.27 2023/03/29 19:09:04 op Exp $ */
|
||||
/* $OpenBSD: tags.c,v 1.28 2024/06/14 13:59:26 op Exp $ */
|
||||
|
||||
/*
|
||||
* This file is in the public domain.
|
||||
|
@ -340,7 +340,7 @@ int
|
|||
addctag(char *s)
|
||||
{
|
||||
struct ctag *t = NULL;
|
||||
char *l;
|
||||
char *l, *c;
|
||||
|
||||
if ((t = malloc(sizeof(struct ctag))) == NULL) {
|
||||
dobeep();
|
||||
|
@ -357,6 +357,15 @@ addctag(char *s)
|
|||
*l++ = '\0';
|
||||
if (*l == '\0')
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* Newer universal ctags format abuse vi comments in the
|
||||
* pattern to store extra metadata. Since we don't support it
|
||||
* remove it so the pattern is not mangled.
|
||||
*/
|
||||
if ((c = strstr(l, ";\"")) != NULL)
|
||||
*c = '\0';
|
||||
|
||||
t->pat = strip(l, strlen(l));
|
||||
if (RB_INSERT(tagtree, &tags, t) != NULL) {
|
||||
free(t);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $OpenBSD: ssh-keyscan.1,v 1.49 2023/02/10 06:41:53 jmc Exp $
|
||||
.\" $OpenBSD: ssh-keyscan.1,v 1.51 2024/06/14 05:20:34 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
||||
.\"
|
||||
|
@ -6,7 +6,7 @@
|
|||
.\" permitted provided that due credit is given to the author and the
|
||||
.\" OpenBSD project by leaving this copyright notice intact.
|
||||
.\"
|
||||
.Dd $Mdocdate: February 10 2023 $
|
||||
.Dd $Mdocdate: June 14 2024 $
|
||||
.Dt SSH-KEYSCAN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -14,7 +14,7 @@
|
|||
.Nd gather SSH public keys from servers
|
||||
.Sh SYNOPSIS
|
||||
.Nm ssh-keyscan
|
||||
.Op Fl 46cDHv
|
||||
.Op Fl 46cDHqv
|
||||
.Op Fl f Ar file
|
||||
.Op Fl O Ar option
|
||||
.Op Fl p Ar port
|
||||
|
@ -116,6 +116,9 @@ The default is to print both.
|
|||
Connect to
|
||||
.Ar port
|
||||
on the remote host.
|
||||
.It Fl q
|
||||
Quiet mode:
|
||||
do not print server host name and banners in comments.
|
||||
.It Fl T Ar timeout
|
||||
Set the timeout for connection attempts.
|
||||
If
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: ssh_config.5,v 1.394 2024/02/21 06:01:13 djm Exp $
|
||||
.Dd $Mdocdate: February 21 2024 $
|
||||
.\" $OpenBSD: ssh_config.5,v 1.395 2024/06/14 05:01:22 djm Exp $
|
||||
.Dd $Mdocdate: June 14 2024 $
|
||||
.Dt SSH_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -1262,8 +1262,12 @@ it may be zero or more of:
|
|||
and
|
||||
.Cm skey .
|
||||
.It Cm KexAlgorithms
|
||||
Specifies the available KEX (Key Exchange) algorithms.
|
||||
Specifies the permitted KEX (Key Exchange) algorithms that will be used and
|
||||
their preference order.
|
||||
The selected algorithm will the the first algorithm in this list that
|
||||
the server also supports.
|
||||
Multiple algorithms must be comma-separated.
|
||||
.Pp
|
||||
If the specified list begins with a
|
||||
.Sq +
|
||||
character, then the specified algorithms will be appended to the default set
|
||||
|
@ -1276,6 +1280,7 @@ If the specified list begins with a
|
|||
.Sq ^
|
||||
character, then the specified algorithms will be placed at the head of the
|
||||
default set.
|
||||
.Pp
|
||||
The default is:
|
||||
.Bd -literal -offset indent
|
||||
sntrup761x25519-sha512@openssh.com,
|
||||
|
@ -1287,7 +1292,7 @@ diffie-hellman-group18-sha512,
|
|||
diffie-hellman-group14-sha256
|
||||
.Ed
|
||||
.Pp
|
||||
The list of available key exchange algorithms may also be obtained using
|
||||
The list of supported key exchange algorithms may also be obtained using
|
||||
.Qq ssh -Q kex .
|
||||
.It Cm KnownHostsCommand
|
||||
Specifies a command to use to obtain a list of host keys, in addition to
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: sshd_config.5,v 1.362 2024/06/13 15:06:33 naddy Exp $
|
||||
.Dd $Mdocdate: June 13 2024 $
|
||||
.\" $OpenBSD: sshd_config.5,v 1.363 2024/06/14 05:01:22 djm Exp $
|
||||
.Dd $Mdocdate: June 14 2024 $
|
||||
.Dt SSHD_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -1004,9 +1004,13 @@ file on logout.
|
|||
The default is
|
||||
.Cm yes .
|
||||
.It Cm KexAlgorithms
|
||||
Specifies the available KEX (Key Exchange) algorithms.
|
||||
Specifies the permitted KEX (Key Exchange) algorithms that the server will
|
||||
offer to clients.
|
||||
The ordering of this list is not important, as the client specifies the
|
||||
preference order.
|
||||
Multiple algorithms must be comma-separated.
|
||||
Alternately if the specified list begins with a
|
||||
.Pp
|
||||
If the specified list begins with a
|
||||
.Sq +
|
||||
character, then the specified algorithms will be appended to the default set
|
||||
instead of replacing them.
|
||||
|
@ -1018,6 +1022,7 @@ If the specified list begins with a
|
|||
.Sq ^
|
||||
character, then the specified algorithms will be placed at the head of the
|
||||
default set.
|
||||
.Pp
|
||||
The supported algorithms are:
|
||||
.Pp
|
||||
.Bl -item -compact -offset indent
|
||||
|
@ -1059,7 +1064,7 @@ diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,
|
|||
diffie-hellman-group14-sha256
|
||||
.Ed
|
||||
.Pp
|
||||
The list of available key exchange algorithms may also be obtained using
|
||||
The list of supported key exchange algorithms may also be obtained using
|
||||
.Qq ssh -Q KexAlgorithms .
|
||||
.It Cm ListenAddress
|
||||
Specifies the local addresses
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue