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>
|
# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org>
|
||||||
#
|
#
|
||||||
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
no warnings 'experimental::smartmatch';
|
|
||||||
use feature 'switch';
|
|
||||||
use Errno;
|
use Errno;
|
||||||
use Digest::MD5;
|
use Digest::MD5;
|
||||||
use IO::Socket qw(sockatmark);
|
use IO::Socket qw(sockatmark);
|
||||||
|
@ -40,13 +38,11 @@ sub write_stream {
|
||||||
$ctx->add($char);
|
$ctx->add($char);
|
||||||
print $char
|
print $char
|
||||||
or die ref($self), " print failed: $!";
|
or die ref($self), " print failed: $!";
|
||||||
given ($char) {
|
if ($char =~ /9/) { $char = 'A' }
|
||||||
when(/9/) { $char = 'A' }
|
elsif ($char =~ /Z/) { $char = 'a' }
|
||||||
when(/Z/) { $char = 'a' }
|
elsif ($char =~ /z/) { $char = "\n" }
|
||||||
when(/z/) { $char = "\n" }
|
elsif ($char =~ /\n/) { print STDERR "."; $char = '0' }
|
||||||
when(/\n/) { print STDERR "."; $char = '0' }
|
else { $char++ }
|
||||||
default { $char++ }
|
|
||||||
}
|
|
||||||
if ($self->{sleep}) {
|
if ($self->{sleep}) {
|
||||||
IO::Handle::flush(\*STDOUT);
|
IO::Handle::flush(\*STDOUT);
|
||||||
sleep $self->{sleep};
|
sleep $self->{sleep};
|
||||||
|
@ -73,28 +69,31 @@ sub write_oob {
|
||||||
my $char = '0';
|
my $char = '0';
|
||||||
for (my $i = 1; $i < $len; $i++) {
|
for (my $i = 1; $i < $len; $i++) {
|
||||||
$msg .= $char;
|
$msg .= $char;
|
||||||
given ($char) {
|
if ($char =~ /9/) {
|
||||||
when(/9/) {
|
$ctx->add("[$char]");
|
||||||
$ctx->add("[$char]");
|
defined(send(STDOUT, $msg, MSG_OOB))
|
||||||
defined(send(STDOUT, $msg, MSG_OOB))
|
or die ref($self), " send OOB failed: $!";
|
||||||
or die ref($self), " send OOB failed: $!";
|
# If tcp urgent data is sent too fast,
|
||||||
# If tcp urgent data is sent too fast,
|
# it may get overwritten and lost.
|
||||||
# it may get overwritten and lost.
|
sleep .1;
|
||||||
sleep .1;
|
$msg = "";
|
||||||
$msg = "";
|
$char = 'A';
|
||||||
$char = 'A';
|
} elsif ($char =~ /Z/) {
|
||||||
}
|
$ctx->add($char);
|
||||||
when(/Z/) { $ctx->add($char); $char = 'a' }
|
$char = 'a';
|
||||||
when(/z/) { $ctx->add($char); $char = "\n" }
|
} elsif ($char =~ /z/) {
|
||||||
when(/\n/) {
|
$ctx->add($char);
|
||||||
$ctx->add($char);
|
$char = "\n";
|
||||||
defined(send(STDOUT, $msg, 0))
|
} elsif ($char =~ /\n/) {
|
||||||
or die ref($self), " send failed: $!";
|
$ctx->add($char);
|
||||||
print STDERR ".";
|
defined(send(STDOUT, $msg, 0))
|
||||||
$msg = "";
|
or die ref($self), " send failed: $!";
|
||||||
$char = '0';
|
print STDERR ".";
|
||||||
}
|
$msg = "";
|
||||||
default { $ctx->add($char); $char++ }
|
$char = '0';
|
||||||
|
} else {
|
||||||
|
$ctx->add($char);
|
||||||
|
$char++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($len) {
|
if ($len) {
|
||||||
|
@ -125,13 +124,11 @@ sub write_datagram {
|
||||||
for (my $i = 1; $i < $l; $i++) {
|
for (my $i = 1; $i < $l; $i++) {
|
||||||
$ctx->add($char);
|
$ctx->add($char);
|
||||||
$string .= $char;
|
$string .= $char;
|
||||||
given ($char) {
|
if ($char =~ /9/) { $char = 'A' }
|
||||||
when(/9/) { $char = 'A' }
|
elsif ($char =~ /Z/) { $char = 'a' }
|
||||||
when(/Z/) { $char = 'a' }
|
elsif ($char =~ /z/) { $char = "\n" }
|
||||||
when(/z/) { $char = "\n" }
|
elsif ($char =~ /\n/) { $char = '0' }
|
||||||
when(/\n/) { $char = '0' }
|
else { $char++ }
|
||||||
default { $char++ }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ($l) {
|
if ($l) {
|
||||||
$ctx->add("\n");
|
$ctx->add("\n");
|
||||||
|
@ -311,10 +308,12 @@ sub relay_copy {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $protocol = $self->{protocol} || "tcp";
|
my $protocol = $self->{protocol} || "tcp";
|
||||||
|
|
||||||
given ($protocol) {
|
if ($protocol =~ /tcp/) {
|
||||||
when (/tcp/) { relay_copy_stream($self, @_) }
|
relay_copy_stream($self, @_);
|
||||||
when (/udp/) { relay_copy_datagram($self, @_) }
|
} elsif ($protocol =~ /udp/) {
|
||||||
default { die ref($self), " unknown protocol name: $protocol" }
|
relay_copy_datagram($self, @_);
|
||||||
|
} else {
|
||||||
|
die ref($self), " unknown protocol name: $protocol";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,10 +436,12 @@ sub relay_splice {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $protocol = $self->{protocol} || "tcp";
|
my $protocol = $self->{protocol} || "tcp";
|
||||||
|
|
||||||
given ($protocol) {
|
if ($protocol =~ /tcp/) {
|
||||||
when (/tcp/) { relay_splice_stream($self, @_) }
|
relay_splice_stream($self, @_);
|
||||||
when (/udp/) { relay_splice_datagram($self, @_) }
|
} elsif ($protocol =~ /udp/) {
|
||||||
default { die ref($self), " unknown protocol name: $protocol" }
|
relay_splice_datagram($self, @_);
|
||||||
|
} else {
|
||||||
|
die ref($self), " unknown protocol name: $protocol";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,10 +449,12 @@ sub relay {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $forward = $self->{forward};
|
my $forward = $self->{forward};
|
||||||
|
|
||||||
given ($forward) {
|
if ($forward =~ /copy/) {
|
||||||
when (/copy/) { relay_copy($self, @_) }
|
relay_copy($self, @_);
|
||||||
when (/splice/) { relay_splice($self, @_) }
|
} elsif ($forward =~ /splice/) {
|
||||||
default { die ref($self), " unknown forward name: $forward" }
|
relay_splice($self, @_);
|
||||||
|
} else {
|
||||||
|
die ref($self), " unknown forward name: $forward";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $soerror;
|
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
|
OPENSSL?= yes
|
||||||
|
|
||||||
|
@ -103,7 +103,8 @@ LTESTS= connect \
|
||||||
match-subsystem \
|
match-subsystem \
|
||||||
agent-pkcs11-restrict \
|
agent-pkcs11-restrict \
|
||||||
agent-pkcs11-cert \
|
agent-pkcs11-cert \
|
||||||
penalty
|
penalty \
|
||||||
|
penalty-expire
|
||||||
|
|
||||||
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
|
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
|
||||||
INTEROP_TESTS+= dropbear-ciphers dropbear-kex
|
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
|
start_sshd
|
||||||
}
|
}
|
||||||
|
|
||||||
conf "noauth:10s authfail:6s grace-exceeded:10s min:8s max:20s"
|
conf "authfail:30s min:50s max:200s"
|
||||||
|
|
||||||
verbose "test connect"
|
verbose "test connect"
|
||||||
${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed"
|
${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
|
# These should be refused by the active penalty
|
||||||
${SSH} -F $OBJ/ssh_config somehost true && fail "authfail not rejected"
|
${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"
|
${SSH} -F $OBJ/ssh_config somehost true && fail "repeat authfail not rejected"
|
||||||
|
|
||||||
# Penalty should have expired, this should succeed.
|
conf "noauth:100s"
|
||||||
sleep 8
|
${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed"
|
||||||
${SSH} -F $OBJ/ssh_config somehost true || fail "authfail not expired"
|
|
||||||
|
|
||||||
verbose "penalty for no authentication"
|
verbose "penalty for no authentication"
|
||||||
${SSHKEYSCAN} -t ssh-ed25519 -p $PORT 127.0.0.1 >/dev/null || fatal "keyscan failed"
|
${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>
|
# Copyright (c) 2010-2021 Alexander Bluhm <bluhm@openbsd.org>
|
||||||
#
|
#
|
||||||
|
@ -16,10 +16,9 @@
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
no warnings 'experimental::smartmatch';
|
|
||||||
use feature 'switch';
|
|
||||||
use Errno;
|
use Errno;
|
||||||
use Digest::MD5;
|
use Digest::MD5;
|
||||||
|
use POSIX;
|
||||||
use Socket;
|
use Socket;
|
||||||
use Socket6;
|
use Socket6;
|
||||||
use IO::Socket;
|
use IO::Socket;
|
||||||
|
@ -63,13 +62,11 @@ sub write_char {
|
||||||
$ctx->add($char);
|
$ctx->add($char);
|
||||||
print $char
|
print $char
|
||||||
or die ref($self), " print failed: $!";
|
or die ref($self), " print failed: $!";
|
||||||
given ($char) {
|
if ($char =~ /9/) { $char = 'A' }
|
||||||
when(/9/) { $char = 'A' }
|
elsif ($char =~ /Z/) { $char = 'a' }
|
||||||
when(/Z/) { $char = 'a' }
|
elsif ($char =~ /z/) { $char = "\n" }
|
||||||
when(/z/) { $char = "\n" }
|
elsif ($char =~ /\n/) { print STDERR "."; $char = '0' }
|
||||||
when(/\n/) { print STDERR "."; $char = '0' }
|
else { $char++ }
|
||||||
default { $char++ }
|
|
||||||
}
|
|
||||||
if ($self->{sleep}) {
|
if ($self->{sleep}) {
|
||||||
IO::Handle::flush(\*STDOUT);
|
IO::Handle::flush(\*STDOUT);
|
||||||
sleep $self->{sleep};
|
sleep $self->{sleep};
|
||||||
|
@ -313,7 +310,6 @@ sub read_multipart {
|
||||||
|
|
||||||
print STDERR "LEN: ", $len, "\n";
|
print STDERR "LEN: ", $len, "\n";
|
||||||
print STDERR "MD5: ", $ctx->hexdigest, "\n";
|
print STDERR "MD5: ", $ctx->hexdigest, "\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub errignore {
|
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>
|
# Copyright (c) 2010-2021 Alexander Bluhm <bluhm@openbsd.org>
|
||||||
#
|
#
|
||||||
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
no warnings 'experimental::smartmatch';
|
|
||||||
use feature 'switch';
|
|
||||||
use Errno;
|
use Errno;
|
||||||
use Digest::MD5;
|
use Digest::MD5;
|
||||||
use Socket;
|
use Socket;
|
||||||
|
@ -125,13 +123,11 @@ sub write_char {
|
||||||
$ctx->add($char);
|
$ctx->add($char);
|
||||||
print $char
|
print $char
|
||||||
or die ref($self), " print failed: $!";
|
or die ref($self), " print failed: $!";
|
||||||
given ($char) {
|
if ($char =~ /9/) { $char = 'A' }
|
||||||
when(/9/) { $char = 'A' }
|
elsif ($char =~ /Z/) { $char = 'a' }
|
||||||
when(/Z/) { $char = 'a' }
|
elsif ($char =~ /z/) { $char = "\n" }
|
||||||
when(/z/) { $char = "\n" }
|
elsif ($char =~ /\n/) { print STDERR "."; $char = '0' }
|
||||||
when(/\n/) { print STDERR "."; $char = '0' }
|
else { $char++ }
|
||||||
default { $char++ }
|
|
||||||
}
|
|
||||||
if ($self->{sleep}) {
|
if ($self->{sleep}) {
|
||||||
IO::Handle::flush(\*STDOUT);
|
IO::Handle::flush(\*STDOUT);
|
||||||
sleep $self->{sleep};
|
sleep $self->{sleep};
|
||||||
|
@ -521,6 +517,15 @@ sub check_logs {
|
||||||
and die "relayd lost child";
|
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 {
|
sub check_len {
|
||||||
my ($c, $r, $s, %args) = @_;
|
my ($c, $r, $s, %args) = @_;
|
||||||
|
|
||||||
|
@ -531,7 +536,7 @@ sub check_len {
|
||||||
unless $args{client}{nocheck};
|
unless $args{client}{nocheck};
|
||||||
@slen = $s->loggrep(qr/^LEN: /) or die "no server len"
|
@slen = $s->loggrep(qr/^LEN: /) or die "no server len"
|
||||||
unless $args{server}{nocheck};
|
unless $args{server}{nocheck};
|
||||||
!@clen || !@slen || @clen ~~ @slen
|
!@clen || !@slen || array_eq \@clen, \@slen
|
||||||
or die "client: @clen", "server: @slen", "len mismatch";
|
or die "client: @clen", "server: @slen", "len mismatch";
|
||||||
!defined($args{len}) || !$clen[0] || $clen[0] eq "LEN: $args{len}\n"
|
!defined($args{len}) || !$clen[0] || $clen[0] eq "LEN: $args{len}\n"
|
||||||
or die "client: $clen[0]", "len $args{len} expected";
|
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>
|
# Copyright (c) 2010-2021 Alexander Bluhm <bluhm@openbsd.org>
|
||||||
#
|
#
|
||||||
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
no warnings 'experimental::smartmatch';
|
|
||||||
use feature 'switch';
|
|
||||||
use Errno;
|
use Errno;
|
||||||
use List::Util qw(first);
|
use List::Util qw(first);
|
||||||
use Socket;
|
use Socket;
|
||||||
|
@ -152,12 +150,10 @@ sub generate_chars {
|
||||||
my $char = '0';
|
my $char = '0';
|
||||||
for (my $i = 0; $i < $len; $i++) {
|
for (my $i = 0; $i < $len; $i++) {
|
||||||
$msg .= $char;
|
$msg .= $char;
|
||||||
given ($char) {
|
if ($char =~ /9/) { $char = 'A' }
|
||||||
when(/9/) { $char = 'A' }
|
elsif ($char =~ /Z/) { $char = 'a' }
|
||||||
when(/Z/) { $char = 'a' }
|
elsif ($char =~ /z/) { $char = '0' }
|
||||||
when(/z/) { $char = '0' }
|
else { $char++ }
|
||||||
default { $char++ }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $msg;
|
return $msg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,8 +380,8 @@
|
||||||
/* Define to 1 if you have the `memmove' function. */
|
/* Define to 1 if you have the `memmove' function. */
|
||||||
#define HAVE_MEMMOVE 1
|
#define HAVE_MEMMOVE 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||||
#define HAVE_MEMORY_H 1
|
/* #undef HAVE_MINIX_CONFIG_H */
|
||||||
|
|
||||||
/* Define to 1 if you have the <netdb.h> header file. */
|
/* Define to 1 if you have the <netdb.h> header file. */
|
||||||
#define HAVE_NETDB_H 1
|
#define HAVE_NETDB_H 1
|
||||||
|
@ -588,6 +588,9 @@
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
#define HAVE_STDINT_H 1
|
#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 to 1 if you have the <stdlib.h> header file. */
|
||||||
#define HAVE_STDLIB_H 1
|
#define HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
@ -690,6 +693,9 @@
|
||||||
/* Define to 1 if you have the <vfork.h> header file. */
|
/* Define to 1 if you have the <vfork.h> header file. */
|
||||||
/* #undef HAVE_VFORK_H */
|
/* #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. */
|
/* Define to 1 if you have the <windows.h> header file. */
|
||||||
/* #undef HAVE_WINDOWS_H */
|
/* #undef HAVE_WINDOWS_H */
|
||||||
|
|
||||||
|
@ -773,7 +779,7 @@
|
||||||
#define PACKAGE_NAME "unbound"
|
#define PACKAGE_NAME "unbound"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* 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 to the one symbol short name of this package. */
|
||||||
#define PACKAGE_TARNAME "unbound"
|
#define PACKAGE_TARNAME "unbound"
|
||||||
|
@ -782,7 +788,7 @@
|
||||||
#define PACKAGE_URL ""
|
#define PACKAGE_URL ""
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "1.19.3"
|
#define PACKAGE_VERSION "1.20.0"
|
||||||
|
|
||||||
/* default pidfile location */
|
/* default pidfile location */
|
||||||
#define PIDFILE ""
|
#define PIDFILE ""
|
||||||
|
@ -805,7 +811,7 @@
|
||||||
#define ROOT_CERT_FILE "/var/unbound/etc/icannbundle.pem"
|
#define ROOT_CERT_FILE "/var/unbound/etc/icannbundle.pem"
|
||||||
|
|
||||||
/* version number for resource files */
|
/* 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 */
|
/* Directory to chdir to */
|
||||||
#define RUN_DIR "/var/unbound/etc"
|
#define RUN_DIR "/var/unbound/etc"
|
||||||
|
@ -831,7 +837,9 @@
|
||||||
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
||||||
/* #undef SODIUM_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
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
/* use default strptime. */
|
/* use default strptime. */
|
||||||
|
@ -927,21 +935,87 @@
|
||||||
#ifndef _ALL_SOURCE
|
#ifndef _ALL_SOURCE
|
||||||
# define _ALL_SOURCE 1
|
# define _ALL_SOURCE 1
|
||||||
#endif
|
#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. */
|
/* Enable GNU extensions on systems that have them. */
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
# define _GNU_SOURCE 1
|
# define _GNU_SOURCE 1
|
||||||
#endif
|
#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
|
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||||
#endif
|
#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. */
|
/* Enable extensions on HP NonStop. */
|
||||||
#ifndef _TANDEM_SOURCE
|
#ifndef _TANDEM_SOURCE
|
||||||
# define _TANDEM_SOURCE 1
|
# define _TANDEM_SOURCE 1
|
||||||
#endif
|
#endif
|
||||||
/* Enable general extensions on Solaris. */
|
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||||
#ifndef __EXTENSIONS__
|
to make mbstate_t available. */
|
||||||
# define __EXTENSIONS__ 1
|
#ifndef _XOPEN_SOURCE
|
||||||
|
/* # undef _XOPEN_SOURCE */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -967,11 +1041,6 @@
|
||||||
`char[]'. */
|
`char[]'. */
|
||||||
#define YYTEXT_POINTER 1
|
#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. */
|
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||||
/* #undef _FILE_OFFSET_BITS */
|
/* #undef _FILE_OFFSET_BITS */
|
||||||
|
|
||||||
|
@ -981,18 +1050,8 @@
|
||||||
/* Define for large files, on AIX-style hosts. */
|
/* Define for large files, on AIX-style hosts. */
|
||||||
/* #undef _LARGE_FILES */
|
/* #undef _LARGE_FILES */
|
||||||
|
|
||||||
/* Define to 1 if on MINIX. */
|
|
||||||
/* #undef _MINIX */
|
|
||||||
|
|
||||||
/* Enable for compile on Minix */
|
/* Enable for compile on Minix */
|
||||||
/* #undef _NETBSD_SOURCE */
|
#define _NETBSD_SOURCE 1
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
|
|
||||||
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
||||||
compiled for windows. */
|
compiled for windows. */
|
||||||
|
@ -1034,7 +1093,7 @@
|
||||||
/* Define to `long int' if <sys/types.h> does not define. */
|
/* Define to `long int' if <sys/types.h> does not define. */
|
||||||
/* #undef off_t */
|
/* #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 */
|
/* #undef pid_t */
|
||||||
|
|
||||||
/* Define to 'int' if not defined */
|
/* Define to 'int' if not defined */
|
||||||
|
|
|
@ -71,6 +71,7 @@ forwards_create(void)
|
||||||
sizeof(struct iter_forwards));
|
sizeof(struct iter_forwards));
|
||||||
if(!fwd)
|
if(!fwd)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
lock_rw_init(&fwd->lock);
|
||||||
return fwd;
|
return fwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +101,7 @@ forwards_delete(struct iter_forwards* fwd)
|
||||||
{
|
{
|
||||||
if(!fwd)
|
if(!fwd)
|
||||||
return;
|
return;
|
||||||
|
lock_rw_destroy(&fwd->lock);
|
||||||
fwd_del_tree(fwd);
|
fwd_del_tree(fwd);
|
||||||
free(fwd);
|
free(fwd);
|
||||||
}
|
}
|
||||||
|
@ -332,45 +334,64 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||||
int
|
int
|
||||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
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_del_tree(fwd);
|
||||||
fwd->tree = rbtree_create(fwd_cmp);
|
fwd->tree = rbtree_create(fwd_cmp);
|
||||||
if(!fwd->tree)
|
if(!fwd->tree)
|
||||||
return 0;
|
return 0;
|
||||||
|
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
|
||||||
|
|
||||||
|
lock_rw_wrlock(&fwd->lock);
|
||||||
/* read forward zones */
|
/* read forward zones */
|
||||||
if(!read_forwards(fwd, cfg))
|
if(!read_forwards(fwd, cfg)) {
|
||||||
|
lock_rw_unlock(&fwd->lock);
|
||||||
return 0;
|
return 0;
|
||||||
if(!make_stub_holes(fwd, cfg))
|
}
|
||||||
|
if(!make_stub_holes(fwd, cfg)) {
|
||||||
|
lock_rw_unlock(&fwd->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
fwd_init_parents(fwd);
|
fwd_init_parents(fwd);
|
||||||
|
lock_rw_unlock(&fwd->lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
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;
|
struct iter_forward_zone key;
|
||||||
|
int has_dp;
|
||||||
key.node.key = &key;
|
key.node.key = &key;
|
||||||
key.dclass = qclass;
|
key.dclass = qclass;
|
||||||
key.name = qname;
|
key.name = qname;
|
||||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||||
res = rbtree_search(fwd->tree, &key);
|
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||||
if(res) return ((struct iter_forward_zone*)res)->dp;
|
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
||||||
return NULL;
|
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*
|
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 */
|
/* lookup the forward zone in the tree */
|
||||||
rbnode_type* res = NULL;
|
rbnode_type* res = NULL;
|
||||||
struct iter_forward_zone *result;
|
struct iter_forward_zone *result;
|
||||||
struct iter_forward_zone key;
|
struct iter_forward_zone key;
|
||||||
|
int has_dp;
|
||||||
key.node.key = &key;
|
key.node.key = &key;
|
||||||
key.dclass = qclass;
|
key.dclass = qclass;
|
||||||
key.name = qname;
|
key.name = qname;
|
||||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
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)) {
|
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
|
||||||
/* exact */
|
/* exact */
|
||||||
result = (struct iter_forward_zone*)res;
|
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) */
|
/* smaller element (or no element) */
|
||||||
int m;
|
int m;
|
||||||
result = (struct iter_forward_zone*)res;
|
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;
|
return NULL;
|
||||||
|
}
|
||||||
/* count number of labels matched */
|
/* count number of labels matched */
|
||||||
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
||||||
key.namelabs, &m);
|
key.namelabs, &m);
|
||||||
|
@ -389,20 +412,22 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||||
result = result->parent;
|
result = result->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(result)
|
has_dp = result && result->dp;
|
||||||
return result->dp;
|
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
|
||||||
return NULL;
|
return has_dp?result->dp:NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
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;
|
uint8_t root = 0;
|
||||||
return forwards_lookup(fwd, &root, qclass);
|
return forwards_lookup(fwd, &root, qclass, nolock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* Finds next root item in forwards lookup tree.
|
||||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
* 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;
|
struct iter_forward_zone key;
|
||||||
rbnode_type* n;
|
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 */
|
/* root not first item? search for higher items */
|
||||||
*dclass = p->dclass + 1;
|
*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
|
/* 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
|
* 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 */
|
/* not a root node, return next higher item */
|
||||||
*dclass = p->dclass+1;
|
*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
|
size_t
|
||||||
forwards_get_mem(struct iter_forwards* fwd)
|
forwards_get_mem(struct iter_forwards* fwd)
|
||||||
{
|
{
|
||||||
|
@ -458,10 +494,12 @@ forwards_get_mem(struct iter_forwards* fwd)
|
||||||
size_t s;
|
size_t s;
|
||||||
if(!fwd)
|
if(!fwd)
|
||||||
return 0;
|
return 0;
|
||||||
|
lock_rw_rdlock(&fwd->lock);
|
||||||
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
||||||
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
||||||
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
||||||
}
|
}
|
||||||
|
lock_rw_unlock(&fwd->lock);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,49 +515,78 @@ fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
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) {
|
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
||||||
(void)rbtree_delete(fwd->tree, &z->node);
|
(void)rbtree_delete(fwd->tree, &z->node);
|
||||||
fwd_zone_free(z);
|
fwd_zone_free(z);
|
||||||
}
|
}
|
||||||
if(!forwards_insert(fwd, c, dp))
|
if(!forwards_insert(fwd, c, dp)) {
|
||||||
return 0;
|
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||||
fwd_init_parents(fwd);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
||||||
{
|
|
||||||
struct iter_forward_zone *z;
|
|
||||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
|
||||||
return; /* nothing to do */
|
|
||||||
(void)rbtree_delete(fwd->tree, &z->node);
|
|
||||||
fwd_zone_free(z);
|
|
||||||
fwd_init_parents(fwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
||||||
{
|
|
||||||
if(!fwd_add_stub_hole(fwd, c, nm)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fwd_init_parents(fwd);
|
fwd_init_parents(fwd);
|
||||||
|
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
forwards_delete_stub_hole(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;
|
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 */
|
return; /* nothing to do */
|
||||||
if(z->dp != NULL)
|
}
|
||||||
return; /* not a stub hole */
|
|
||||||
(void)rbtree_delete(fwd->tree, &z->node);
|
(void)rbtree_delete(fwd->tree, &z->node);
|
||||||
fwd_zone_free(z);
|
fwd_zone_free(z);
|
||||||
fwd_init_parents(fwd);
|
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,
|
||||||
|
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, 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, nm))) {
|
||||||
|
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||||
|
return; /* nothing to do */
|
||||||
|
}
|
||||||
|
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
|
#ifndef ITERATOR_ITER_FWD_H
|
||||||
#define ITERATOR_ITER_FWD_H
|
#define ITERATOR_ITER_FWD_H
|
||||||
#include "util/rbtree.h"
|
#include "util/rbtree.h"
|
||||||
|
#include "util/locks.h"
|
||||||
struct config_file;
|
struct config_file;
|
||||||
struct delegpt;
|
struct delegpt;
|
||||||
|
|
||||||
|
@ -50,6 +51,11 @@ struct delegpt;
|
||||||
* Iterator forward zones structure
|
* Iterator forward zones structure
|
||||||
*/
|
*/
|
||||||
struct iter_forwards {
|
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.
|
* Zones are stored in this tree. Sort order is specially chosen.
|
||||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
* 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
|
* 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 fwd: forward storage.
|
||||||
* @param qname: The qname of the query.
|
* @param qname: The qname of the query.
|
||||||
* @param qclass: The qclass 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.
|
* @return: A delegation point or null.
|
||||||
*/
|
*/
|
||||||
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
|
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
|
||||||
uint16_t qclass);
|
uint16_t qclass, int nolock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find forward zone information
|
* Find forward zone information
|
||||||
* For this qname/qclass find forward zone information, returns delegation
|
* For this qname/qclass find forward zone information, returns delegation
|
||||||
* point with server names and addresses, or NULL if no forwarding is needed.
|
* 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 fwd: forward storage.
|
||||||
* @param qname: The qname of the query.
|
* @param qname: The qname of the query.
|
||||||
* @param qclass: The qclass 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,
|
* @return: A delegation point if the query has to be forwarded to that list,
|
||||||
* otherwise null.
|
* otherwise null.
|
||||||
*/
|
*/
|
||||||
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
|
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
|
* Same as forwards_lookup, but for the root only
|
||||||
* @param fwd: forward storage.
|
* @param fwd: forward storage.
|
||||||
* @param qclass: The qclass 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 root forward exists, otherwise null.
|
* @return: A delegation point if root forward exists, otherwise null.
|
||||||
*/
|
*/
|
||||||
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
|
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.
|
* 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 fwd: the forward storage
|
||||||
* @param qclass: class to look at next, or higher.
|
* @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.
|
* @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
|
* Get memory in use by forward storage
|
||||||
|
* Locks and unlocks the structure.
|
||||||
* @param fwd: forward storage.
|
* @param fwd: forward storage.
|
||||||
* @return bytes in use
|
* @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
|
* Add zone to forward structure. For external use since it recalcs
|
||||||
* the tree parents.
|
* 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 fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param dp: delegation point with name and target nameservers for new
|
* @param dp: delegation point with name and target nameservers for new
|
||||||
* forward zone. malloced.
|
* forward zone. malloced.
|
||||||
|
* @param nolock: Skip locking, locking is handled by the caller.
|
||||||
* @return false on failure (out of memory);
|
* @return false on failure (out of memory);
|
||||||
*/
|
*/
|
||||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
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
|
* Remove zone from forward structure. For external use since it
|
||||||
* recalcs the tree parents.
|
* 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 fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param nm: name of zone (in uncompressed wireformat).
|
* @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
|
* Add stub hole (empty entry in forward table, that makes resolution skip
|
||||||
* a forward-zone because the stub zone should override the forward zone).
|
* a forward-zone because the stub zone should override the forward zone).
|
||||||
* Does not add one if not necessary.
|
* 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 fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param nm: name of zone (in uncompressed wireformat).
|
* @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);
|
* @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.
|
* 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 fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param nm: name of zone (in uncompressed wireformat).
|
* @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,
|
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 */
|
#endif /* ITERATOR_ITER_FWD_H */
|
||||||
|
|
|
@ -57,6 +57,8 @@ hints_create(void)
|
||||||
sizeof(struct iter_hints));
|
sizeof(struct iter_hints));
|
||||||
if(!hints)
|
if(!hints)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
lock_rw_init(&hints->lock);
|
||||||
|
lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
|
||||||
return hints;
|
return hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +85,7 @@ hints_delete(struct iter_hints* hints)
|
||||||
{
|
{
|
||||||
if(!hints)
|
if(!hints)
|
||||||
return;
|
return;
|
||||||
|
lock_rw_destroy(&hints->lock);
|
||||||
hints_del_tree(hints);
|
hints_del_tree(hints);
|
||||||
free(hints);
|
free(hints);
|
||||||
}
|
}
|
||||||
|
@ -438,47 +441,70 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
|
||||||
int
|
int
|
||||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||||
{
|
{
|
||||||
|
int nolock = 1;
|
||||||
|
lock_rw_wrlock(&hints->lock);
|
||||||
hints_del_tree(hints);
|
hints_del_tree(hints);
|
||||||
name_tree_init(&hints->tree);
|
name_tree_init(&hints->tree);
|
||||||
|
|
||||||
/* read root hints */
|
/* read root hints */
|
||||||
if(!read_root_hints_list(hints, cfg))
|
if(!read_root_hints_list(hints, cfg)) {
|
||||||
|
lock_rw_unlock(&hints->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* read stub hints */
|
/* read stub hints */
|
||||||
if(!read_stubs(hints, cfg))
|
if(!read_stubs(hints, cfg)) {
|
||||||
|
lock_rw_unlock(&hints->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* use fallback compiletime root hints */
|
/* use fallback compiletime root hints */
|
||||||
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
if(!hints_find_root(hints, LDNS_RR_CLASS_IN, nolock)) {
|
||||||
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
||||||
cfg->do_ip6);
|
cfg->do_ip6);
|
||||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||||
if(!dp)
|
if(!dp) {
|
||||||
|
lock_rw_unlock(&hints->lock);
|
||||||
return 0;
|
return 0;
|
||||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
|
}
|
||||||
|
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
|
||||||
|
lock_rw_unlock(&hints->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name_tree_init_parents(&hints->tree);
|
name_tree_init_parents(&hints->tree);
|
||||||
|
lock_rw_unlock(&hints->lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
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;
|
uint8_t rootlab = 0;
|
||||||
struct iter_hints_stub *stub;
|
return hints_find(hints, &rootlab, qclass, nolock);
|
||||||
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
|
||||||
&rootlab, 1, 1, qclass);
|
|
||||||
if(!stub)
|
|
||||||
return NULL;
|
|
||||||
return stub->dp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iter_hints_stub*
|
struct iter_hints_stub*
|
||||||
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
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;
|
size_t len;
|
||||||
int labs;
|
int labs;
|
||||||
|
@ -486,14 +512,20 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||||
|
|
||||||
/* first lookup the stub */
|
/* first lookup the stub */
|
||||||
labs = dname_count_size_labels(qname, &len);
|
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,
|
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
|
||||||
len, labs, qclass);
|
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 there is no cache (root prime situation) */
|
||||||
if(cache_dp == NULL) {
|
if(cache_dp == NULL) {
|
||||||
if(r->dp->namelabs != 1)
|
if(r->dp->namelabs != 1)
|
||||||
return r; /* no cache dp, use any non-root stub */
|
return r; /* no cache dp, use any non-root stub */
|
||||||
|
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||||
return NULL;
|
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,
|
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
|
||||||
cache_dp->name, cache_dp->namelabs))
|
cache_dp->name, cache_dp->namelabs))
|
||||||
return r; /* need to prime this stub */
|
return r; /* need to prime this stub */
|
||||||
|
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||||
return NULL;
|
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
|
size_t
|
||||||
|
@ -524,39 +562,52 @@ hints_get_mem(struct iter_hints* hints)
|
||||||
size_t s;
|
size_t s;
|
||||||
struct iter_hints_stub* p;
|
struct iter_hints_stub* p;
|
||||||
if(!hints) return 0;
|
if(!hints) return 0;
|
||||||
|
lock_rw_rdlock(&hints->lock);
|
||||||
s = sizeof(*hints);
|
s = sizeof(*hints);
|
||||||
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
||||||
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
||||||
}
|
}
|
||||||
|
lock_rw_unlock(&hints->lock);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||||
int noprime)
|
int noprime, int nolock)
|
||||||
{
|
{
|
||||||
struct iter_hints_stub *z;
|
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,
|
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||||
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
||||||
(void)rbtree_delete(&hints->tree, &z->node);
|
(void)rbtree_delete(&hints->tree, &z->node);
|
||||||
hints_stub_free(z);
|
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;
|
return 0;
|
||||||
|
}
|
||||||
name_tree_init_parents(&hints->tree);
|
name_tree_init_parents(&hints->tree);
|
||||||
|
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
struct iter_hints_stub *z;
|
||||||
size_t len;
|
size_t len;
|
||||||
int labs = dname_count_size_labels(nm, &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,
|
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 */
|
return; /* nothing to do */
|
||||||
|
}
|
||||||
(void)rbtree_delete(&hints->tree, &z->node);
|
(void)rbtree_delete(&hints->tree, &z->node);
|
||||||
hints_stub_free(z);
|
hints_stub_free(z);
|
||||||
name_tree_init_parents(&hints->tree);
|
name_tree_init_parents(&hints->tree);
|
||||||
|
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#ifndef ITERATOR_ITER_HINTS_H
|
#ifndef ITERATOR_ITER_HINTS_H
|
||||||
#define ITERATOR_ITER_HINTS_H
|
#define ITERATOR_ITER_HINTS_H
|
||||||
#include "util/storage/dnstree.h"
|
#include "util/storage/dnstree.h"
|
||||||
|
#include "util/locks.h"
|
||||||
struct iter_env;
|
struct iter_env;
|
||||||
struct config_file;
|
struct config_file;
|
||||||
struct delegpt;
|
struct delegpt;
|
||||||
|
@ -51,6 +52,10 @@ struct delegpt;
|
||||||
* Iterator hints structure
|
* Iterator hints structure
|
||||||
*/
|
*/
|
||||||
struct iter_hints {
|
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.
|
* Hints are stored in this tree. Sort order is specially chosen.
|
||||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
* 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);
|
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 hints: hint storage.
|
||||||
|
* @param qname: the qname that generated the delegation point.
|
||||||
* @param qclass: class for which root hints are requested. host order.
|
* @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.
|
* @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).
|
* 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 hints: hint storage
|
||||||
* @param qclass: class for which root hints are sought.
|
* @param qclass: class for which root hints are sought.
|
||||||
* 0 means give the first available root hints class.
|
* 0 means give the first available root hints class.
|
||||||
* x means, give class x or a higher class if any.
|
* x means, give class x or a higher class if any.
|
||||||
* returns the found class in this variable.
|
* 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.
|
* @return true if a root hint class is found.
|
||||||
* false if not root hint class is found (qclass may have been changed).
|
* 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
|
* Given a qname/qclass combination, and the delegation point from the cache
|
||||||
* for this qname/qclass, determine if this combination indicates that a
|
* for this qname/qclass, determine if this combination indicates that a
|
||||||
* stub hint exists and must be primed.
|
* 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 hints: hint storage.
|
||||||
* @param qname: The qname that generated the delegation point.
|
* @param qname: The qname that generated the delegation point.
|
||||||
* @param qclass: The qclass that generated the delegation point.
|
* @param qclass: The qclass that generated the delegation point.
|
||||||
* @param dp: The cache generated 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
|
* @return: A priming delegation point if there is a stub hint that must
|
||||||
* be primed, otherwise null.
|
* be primed, otherwise null.
|
||||||
*/
|
*/
|
||||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
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
|
* Get memory in use by hints
|
||||||
|
* Locks and unlocks the structure.
|
||||||
* @param hints: hint storage.
|
* @param hints: hint storage.
|
||||||
* @return bytes in use
|
* @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
|
* Add stub to hints structure. For external use since it recalcs
|
||||||
* the tree parents.
|
* 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 hints: the hints data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param dp: delegation point with name and target nameservers for new
|
* @param dp: delegation point with name and target nameservers for new
|
||||||
* hints stub. malloced.
|
* hints stub. malloced.
|
||||||
* @param noprime: set noprime option to true or false on new hint stub.
|
* @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);
|
* @return false on failure (out of memory);
|
||||||
*/
|
*/
|
||||||
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
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
|
* Remove stub from hints structure. For external use since it
|
||||||
* recalcs the tree parents.
|
* 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 hints: the hints data structure
|
||||||
* @param c: class of stub zone
|
* @param c: class of stub zone
|
||||||
* @param nm: name of stub zone (in uncompressed wireformat).
|
* @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 */
|
#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* c)
|
||||||
{
|
{
|
||||||
uint16_t c1 = *c, c2 = *c;
|
uint16_t c1 = *c, c2 = *c;
|
||||||
int r1 = hints_next_root(hints, &c1);
|
int r1, r2;
|
||||||
int r2 = forwards_next_root(fwd, &c2);
|
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 */
|
if(!r1 && !r2) /* got none, end of list */
|
||||||
return 0;
|
return 0;
|
||||||
else if(!r1) /* got one, return that */
|
else if(!r1) /* got one, return that */
|
||||||
|
@ -1450,15 +1459,21 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
|
||||||
|
|
||||||
int
|
int
|
||||||
iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
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 iter_hints_stub *stub;
|
||||||
struct delegpt *dp;
|
struct delegpt *dp;
|
||||||
|
int nolock = 1;
|
||||||
|
|
||||||
/* Check for stub. */
|
/* 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,
|
stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
|
||||||
qinf->qclass, NULL);
|
qinf->qclass, NULL, nolock);
|
||||||
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
|
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass,
|
||||||
|
nolock);
|
||||||
|
|
||||||
/* see if forward or stub is more pertinent */
|
/* see if forward or stub is more pertinent */
|
||||||
if(stub && stub->dp && dp) {
|
if(stub && stub->dp && dp) {
|
||||||
|
@ -1472,7 +1487,9 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||||
|
|
||||||
/* check stub */
|
/* check stub */
|
||||||
if (stub != NULL && stub->dp != NULL) {
|
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 qname[255+1];
|
||||||
char dpname[255+1];
|
char dpname[255+1];
|
||||||
dname_str(qinf->qname, qname);
|
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);
|
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
|
||||||
}
|
}
|
||||||
if(retdpname) {
|
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;
|
*retdpnamelen = stub->dp->namelen;
|
||||||
}
|
}
|
||||||
return (stub->dp->no_cache);
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
|
return stub_no_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for forward. */
|
/* Check for forward. */
|
||||||
if (dp) {
|
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 qname[255+1];
|
||||||
char dpname[255+1];
|
char dpname[255+1];
|
||||||
dname_str(qinf->qname, qname);
|
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);
|
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
|
||||||
}
|
}
|
||||||
if(retdpname) {
|
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;
|
*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) {
|
if(retdpname) {
|
||||||
*retdpname = NULL;
|
*retdpname = NULL;
|
||||||
*retdpnamelen = 0;
|
*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
|
* Used for NXDOMAIN checks, above that it is an nxdomain from a
|
||||||
* different server and zone. You can pass NULL to not get it.
|
* different server and zone. You can pass NULL to not get it.
|
||||||
* @param retdpnamelen: returns the length of the dpname.
|
* @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.
|
* @return true if no_cache is set in stub or fwd.
|
||||||
*/
|
*/
|
||||||
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
|
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
|
* Set support for IP4 and IP6 depending on outgoing interfaces
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "iterator/iter_priv.h"
|
#include "iterator/iter_priv.h"
|
||||||
#include "validator/val_neg.h"
|
#include "validator/val_neg.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
|
#include "services/cache/rrset.h"
|
||||||
#include "services/cache/infra.h"
|
#include "services/cache/infra.h"
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
#include "util/module.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 */
|
/** see if last resort is possible - does config allow queries to parent */
|
||||||
static int
|
static int
|
||||||
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
|
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t ATTR_UNUSED(nmlen),
|
||||||
uint16_t qclass, struct delegpt** retdp)
|
uint16_t qclass, int* have_dp, struct delegpt** retdp,
|
||||||
|
struct regional* region)
|
||||||
{
|
{
|
||||||
struct delegpt* fwddp;
|
struct delegpt* dp = NULL;
|
||||||
struct iter_hints_stub* stub;
|
int nolock = 0;
|
||||||
int labs = dname_count_labels(nm);
|
|
||||||
/* do not process a last resort (the parent side) if a stub
|
/* do not process a last resort (the parent side) if a stub
|
||||||
* or forward is configured, because we do not want to go 'above'
|
* or forward is configured, because we do not want to go 'above'
|
||||||
* the configured servers */
|
* the configured servers */
|
||||||
if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
|
if(!dname_is_root(nm) &&
|
||||||
name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
|
(dp = hints_find(env->hints, nm, qclass, nolock)) &&
|
||||||
/* has_parent side is turned off for stub_first, where we
|
/* has_parent side is turned off for stub_first, where we
|
||||||
* are allowed to go to the parent */
|
* are allowed to go to the parent */
|
||||||
stub->dp->has_parent_side_NS) {
|
dp->has_parent_side_NS) {
|
||||||
if(retdp) *retdp = stub->dp;
|
if(retdp) *retdp = delegpt_copy(dp, region);
|
||||||
|
lock_rw_unlock(&env->hints->lock);
|
||||||
|
if(have_dp) *have_dp = 1;
|
||||||
return 0;
|
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
|
/* has_parent_side is turned off for forward_first, where
|
||||||
* we are allowed to go to the parent */
|
* we are allowed to go to the parent */
|
||||||
fwddp->has_parent_side_NS) {
|
dp->has_parent_side_NS) {
|
||||||
if(retdp) *retdp = fwddp;
|
if(retdp) *retdp = delegpt_copy(dp, region);
|
||||||
|
lock_rw_unlock(&env->fwds->lock);
|
||||||
|
if(have_dp) *have_dp = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||||
|
if(dp) { lock_rw_unlock(&env->fwds->lock); }
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,10 +888,11 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||||
{
|
{
|
||||||
struct delegpt* dp;
|
struct delegpt* dp;
|
||||||
struct module_qstate* subq;
|
struct module_qstate* subq;
|
||||||
|
int nolock = 0;
|
||||||
verbose(VERB_DETAIL, "priming . %s NS",
|
verbose(VERB_DETAIL, "priming . %s NS",
|
||||||
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)?
|
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)?
|
||||||
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)->name:"??");
|
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) {
|
if(!dp) {
|
||||||
verbose(VERB_ALGO, "Cannot prime due to lack of hints");
|
verbose(VERB_ALGO, "Cannot prime due to lack of hints");
|
||||||
return 0;
|
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,
|
if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS,
|
||||||
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
|
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
|
||||||
&subq, 0, 0)) {
|
&subq, 0, 0)) {
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
verbose(VERB_ALGO, "could not prime root");
|
verbose(VERB_ALGO, "could not prime root");
|
||||||
return 0;
|
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.
|
* copy dp, it is now part of the root prime query.
|
||||||
* dp was part of in the fixed hints structure. */
|
* dp was part of in the fixed hints structure. */
|
||||||
subiq->dp = delegpt_copy(dp, subq->region);
|
subiq->dp = delegpt_copy(dp, subq->region);
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
if(!subiq->dp) {
|
if(!subiq->dp) {
|
||||||
log_err("out of memory priming root, copydp");
|
log_err("out of memory priming root, copydp");
|
||||||
fptr_ok(fptr_whitelist_modenv_kill_sub(
|
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->num_target_queries = 0;
|
||||||
subiq->dnssec_expected = iter_indicates_dnssec(
|
subiq->dnssec_expected = iter_indicates_dnssec(
|
||||||
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
|
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. */
|
/* 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 iter_hints_stub* stub;
|
||||||
struct delegpt* stub_dp;
|
struct delegpt* stub_dp;
|
||||||
struct module_qstate* subq;
|
struct module_qstate* subq;
|
||||||
|
int nolock = 0;
|
||||||
|
|
||||||
if(!qname) return 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. */
|
/* The stub (if there is one) does not need priming. */
|
||||||
if(!stub)
|
if(!stub) return 0;
|
||||||
return 0;
|
|
||||||
stub_dp = stub->dp;
|
stub_dp = stub->dp;
|
||||||
/* if we have an auth_zone dp, and stub is equal, don't prime stub
|
/* 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 */
|
* yet, unless we want to fallback and avoid the auth_zone */
|
||||||
if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp &&
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* is it a noprime stub (always use) */
|
/* is it a noprime stub (always use) */
|
||||||
if(stub->noprime) {
|
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
|
/* copy the dp out of the fixed hints structure, so that
|
||||||
* it can be changed when servicing this query */
|
* it can be changed when servicing this query */
|
||||||
iq->dp = delegpt_copy(stub_dp, qstate->region);
|
iq->dp = delegpt_copy(stub_dp, qstate->region);
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
if(!iq->dp) {
|
if(!iq->dp) {
|
||||||
log_err("out of memory priming stub");
|
log_err("out of memory priming stub");
|
||||||
errinf(qstate, "malloc failure, priming stub");
|
errinf(qstate, "malloc failure, priming stub");
|
||||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||||
return 1; /* return 1 to make module stop, with error */
|
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);
|
LDNS_RR_TYPE_NS, qclass);
|
||||||
return r;
|
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,
|
if(!generate_sub_request(stub_dp->name, stub_dp->namelen,
|
||||||
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
|
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
|
||||||
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) {
|
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) {
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
verbose(VERB_ALGO, "could not prime stub");
|
verbose(VERB_ALGO, "could not prime stub");
|
||||||
errinf(qstate, "could not generate lookup for stub prime");
|
errinf(qstate, "could not generate lookup for stub prime");
|
||||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
(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. */
|
/* Set the initial delegation point to the hint. */
|
||||||
/* make copy to avoid use of stub dp by different qs/threads */
|
/* make copy to avoid use of stub dp by different qs/threads */
|
||||||
subiq->dp = delegpt_copy(stub_dp, subq->region);
|
subiq->dp = delegpt_copy(stub_dp, subq->region);
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
if(!subiq->dp) {
|
if(!subiq->dp) {
|
||||||
log_err("out of memory priming stub, copydp");
|
log_err("out of memory priming stub, copydp");
|
||||||
fptr_ok(fptr_whitelist_modenv_kill_sub(
|
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->wait_priming_stub = 1;
|
||||||
subiq->dnssec_expected = iter_indicates_dnssec(
|
subiq->dnssec_expected = iter_indicates_dnssec(
|
||||||
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
|
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. */
|
/* 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)
|
if(iq->depth == ie->max_dependency_depth)
|
||||||
return;
|
return;
|
||||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||||
iq->qchase.qclass, NULL))
|
iq->qchase.qclass, NULL, NULL, NULL))
|
||||||
return;
|
return;
|
||||||
/* is this query the same as the nscheck? */
|
/* is this query the same as the nscheck? */
|
||||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
|
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;
|
struct delegpt* dp;
|
||||||
uint8_t* delname = iq->qchase.qname;
|
uint8_t* delname = iq->qchase.qname;
|
||||||
size_t delnamelen = iq->qchase.qname_len;
|
size_t delnamelen = iq->qchase.qname_len;
|
||||||
|
int nolock = 0;
|
||||||
if(iq->refetch_glue && iq->dp) {
|
if(iq->refetch_glue && iq->dp) {
|
||||||
delname = iq->dp->name;
|
delname = iq->dp->name;
|
||||||
delnamelen = iq->dp->namelen;
|
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)
|
if( (iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue)
|
||||||
&& !dname_is_root(iq->qchase.qname))
|
&& !dname_is_root(iq->qchase.qname))
|
||||||
dname_remove_label(&delname, &delnamelen);
|
dname_remove_label(&delname, &delnamelen);
|
||||||
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass);
|
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass,
|
||||||
if(!dp)
|
nolock);
|
||||||
return 0;
|
if(!dp) return 0;
|
||||||
/* send recursion desired to forward addr */
|
/* send recursion desired to forward addr */
|
||||||
iq->chase_flags |= BIT_RD;
|
iq->chase_flags |= BIT_RD;
|
||||||
iq->dp = delegpt_copy(dp, qstate->region);
|
iq->dp = delegpt_copy(dp, qstate->region);
|
||||||
|
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||||
/* iq->dp checked by caller */
|
/* iq->dp checked by caller */
|
||||||
verbose(VERB_ALGO, "forwarding request");
|
verbose(VERB_ALGO, "forwarding request");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1335,6 +1361,7 @@ static int
|
||||||
processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
struct iter_env* ie, int id)
|
struct iter_env* ie, int id)
|
||||||
{
|
{
|
||||||
|
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
|
||||||
uint8_t* delname, *dpname=NULL;
|
uint8_t* delname, *dpname=NULL;
|
||||||
size_t delnamelen, dpnamelen=0;
|
size_t delnamelen, dpnamelen=0;
|
||||||
struct dns_msg* msg = NULL;
|
struct dns_msg* msg = NULL;
|
||||||
|
@ -1381,7 +1408,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
if (iq->refetch_glue &&
|
if (iq->refetch_glue &&
|
||||||
iq->dp &&
|
iq->dp &&
|
||||||
!can_have_last_resort(qstate->env, iq->dp->name,
|
!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;
|
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
|
/* This either results in a query restart (CNAME cache response), a
|
||||||
* terminating response (ANSWER), or a cache miss (null). */
|
* 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. */
|
/* Asked to not query cache. */
|
||||||
verbose(VERB_ALGO, "no-cache set, going to the network");
|
verbose(VERB_ALGO, "no-cache set, going to the network");
|
||||||
qstate->no_cache_lookup = 1;
|
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 = sname;
|
||||||
iq->qchase.qname_len = slen;
|
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
|
/* This *is* a query restart, even if it is a cheap
|
||||||
* one. */
|
* one. */
|
||||||
iq->dp = NULL;
|
iq->dp = NULL;
|
||||||
|
@ -1494,7 +1541,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||||
return next_state(iq, INIT_REQUEST_STATE);
|
return next_state(iq, INIT_REQUEST_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if from cache, NULL, else insert 'cache IP' len=0 */
|
/* if from cache, NULL, else insert 'cache IP' len=0 */
|
||||||
if(qstate->reply_origin)
|
if(qstate->reply_origin)
|
||||||
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
|
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 ||
|
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
|
||||||
(iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
|
(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,
|
/* remove first label from delname, root goes to hints,
|
||||||
* but only to fetch glue, not for qtype=DS. */
|
* but only to fetch glue, not for qtype=DS. */
|
||||||
/* also when prefetching an NS record, fetch it again from
|
/* 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. */
|
* root priming situation. */
|
||||||
if(iq->dp == NULL) {
|
if(iq->dp == NULL) {
|
||||||
int r;
|
int r;
|
||||||
|
int nolock = 0;
|
||||||
/* if under auth zone, no prime needed */
|
/* if under auth zone, no prime needed */
|
||||||
if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
|
if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
|
||||||
return error_response(qstate, id,
|
return error_response(qstate, id,
|
||||||
|
@ -1598,11 +1645,12 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
else if(r)
|
else if(r)
|
||||||
return 0; /* stub prime request made */
|
return 0; /* stub prime request made */
|
||||||
if(forwards_lookup_root(qstate->env->fwds,
|
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 */
|
/* forward zone root, no root prime needed */
|
||||||
/* fill in some dp - safety belt */
|
/* fill in some dp - safety belt */
|
||||||
iq->dp = hints_lookup_root(qstate->env->hints,
|
iq->dp = hints_find_root(qstate->env->hints,
|
||||||
iq->qchase.qclass);
|
iq->qchase.qclass, nolock);
|
||||||
if(!iq->dp) {
|
if(!iq->dp) {
|
||||||
log_err("internal error: no hints dp");
|
log_err("internal error: no hints dp");
|
||||||
errinf(qstate, "no hints for this class");
|
errinf(qstate, "no hints for this class");
|
||||||
|
@ -1610,6 +1658,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
LDNS_RCODE_SERVFAIL);
|
LDNS_RCODE_SERVFAIL);
|
||||||
}
|
}
|
||||||
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
if(!iq->dp) {
|
if(!iq->dp) {
|
||||||
log_err("out of memory in safety belt");
|
log_err("out of memory in safety belt");
|
||||||
errinf(qstate, "malloc failure, 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,
|
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||||
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
|
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
|
||||||
ie->use_nat64)) {
|
ie->use_nat64)) {
|
||||||
struct delegpt* retdp = NULL;
|
int have_dp = 0;
|
||||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
|
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &have_dp, &iq->dp, qstate->region)) {
|
||||||
if(retdp) {
|
if(have_dp) {
|
||||||
verbose(VERB_QUERY, "cache has stub "
|
verbose(VERB_QUERY, "cache has stub "
|
||||||
"or fwd but no addresses, "
|
"or fwd but no addresses, "
|
||||||
"fallback to config");
|
"fallback to config");
|
||||||
iq->dp = delegpt_copy(retdp,
|
if(have_dp && !iq->dp) {
|
||||||
qstate->region);
|
|
||||||
if(!iq->dp) {
|
|
||||||
log_err("out of memory in "
|
log_err("out of memory in "
|
||||||
"stub/fwd fallback");
|
"stub/fwd fallback");
|
||||||
errinf(qstate, "malloc failure, for fallback to config");
|
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)) {
|
if(dname_is_root(iq->dp->name)) {
|
||||||
/* use safety belt */
|
/* use safety belt */
|
||||||
|
int nolock = 0;
|
||||||
verbose(VERB_QUERY, "Cache has root NS but "
|
verbose(VERB_QUERY, "Cache has root NS but "
|
||||||
"no addresses. Fallback to the safety belt.");
|
"no addresses. Fallback to the safety belt.");
|
||||||
iq->dp = hints_lookup_root(qstate->env->hints,
|
iq->dp = hints_find_root(qstate->env->hints,
|
||||||
iq->qchase.qclass);
|
iq->qchase.qclass, nolock);
|
||||||
/* note deleg_msg is from previous lookup,
|
/* note deleg_msg is from previous lookup,
|
||||||
* but RD is on, so it is not used */
|
* but RD is on, so it is not used */
|
||||||
if(!iq->dp) {
|
if(!iq->dp) {
|
||||||
|
@ -1689,6 +1737,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
LDNS_RCODE_REFUSED);
|
LDNS_RCODE_REFUSED);
|
||||||
}
|
}
|
||||||
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
iq->dp = delegpt_copy(iq->dp, qstate->region);
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
if(!iq->dp) {
|
if(!iq->dp) {
|
||||||
log_err("out of memory in safety belt");
|
log_err("out of memory in safety belt");
|
||||||
errinf(qstate, "malloc failure, in safety belt, for root");
|
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;
|
delnamelen = iq->qchase.qname_len;
|
||||||
if(iq->refetch_glue) {
|
if(iq->refetch_glue) {
|
||||||
struct iter_hints_stub* stub;
|
struct iter_hints_stub* stub;
|
||||||
|
int nolock = 0;
|
||||||
if(!iq->dp) {
|
if(!iq->dp) {
|
||||||
log_err("internal or malloc fail: no dp for refetch");
|
log_err("internal or malloc fail: no dp for refetch");
|
||||||
errinf(qstate, "malloc failure, no delegation info");
|
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. */
|
* this is above stub without stub-first. */
|
||||||
stub = hints_lookup_stub(
|
stub = hints_lookup_stub(
|
||||||
qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
|
qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
|
||||||
iq->dp);
|
iq->dp, nolock);
|
||||||
if(!stub || !stub->dp->has_parent_side_NS ||
|
if(!stub || !stub->dp->has_parent_side_NS ||
|
||||||
dname_subdomain_c(iq->dp->name, stub->dp->name)) {
|
dname_subdomain_c(iq->dp->name, stub->dp->name)) {
|
||||||
delname = iq->dp->name;
|
delname = iq->dp->name;
|
||||||
delnamelen = iq->dp->namelen;
|
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(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
|
||||||
if(!dname_is_root(delname))
|
if(!dname_is_root(delname))
|
||||||
|
@ -2062,7 +2114,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
log_assert(iq->dp);
|
log_assert(iq->dp);
|
||||||
|
|
||||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
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
|
/* fail -- no more targets, no more hope of targets, no hope
|
||||||
* of a response. */
|
* of a response. */
|
||||||
errinf(qstate, "all the configured stub or forward servers failed,");
|
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);
|
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||||
}
|
}
|
||||||
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
|
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
|
||||||
struct delegpt* p = hints_lookup_root(qstate->env->hints,
|
struct delegpt* dp;
|
||||||
iq->qchase.qclass);
|
int nolock = 0;
|
||||||
if(p) {
|
dp = hints_find_root(qstate->env->hints,
|
||||||
|
iq->qchase.qclass, nolock);
|
||||||
|
if(dp) {
|
||||||
struct delegpt_addr* a;
|
struct delegpt_addr* a;
|
||||||
iq->chase_flags &= ~BIT_RD; /* go to authorities */
|
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,
|
(void)delegpt_add_ns(iq->dp, qstate->region,
|
||||||
ns->name, ns->lame, ns->tls_auth_name,
|
ns->name, ns->lame, ns->tls_auth_name,
|
||||||
ns->port);
|
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,
|
(void)delegpt_add_addr(iq->dp, qstate->region,
|
||||||
&a->addr, a->addrlen, a->bogus,
|
&a->addr, a->addrlen, a->bogus,
|
||||||
a->lame, a->tls_auth_name, -1, NULL);
|
a->lame, a->tls_auth_name, -1, NULL);
|
||||||
}
|
}
|
||||||
|
lock_rw_unlock(&qstate->env->hints->lock);
|
||||||
}
|
}
|
||||||
iq->dp->has_parent_side_NS = 1;
|
iq->dp->has_parent_side_NS = 1;
|
||||||
} else if(!iq->dp->has_parent_side_NS) {
|
} 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) ||
|
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
|
||||||
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
|
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
|
||||||
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
|
!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 "
|
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
|
||||||
"because it is also a stub/forward,",
|
"because it is also a stub/forward,",
|
||||||
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
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);
|
delegpt_add_unused_targets(iq->dp);
|
||||||
|
|
||||||
if(qstate->env->auth_zones) {
|
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);
|
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) {
|
if(forged_response != NULL) {
|
||||||
qstate->ext_state[id] = module_finished;
|
qstate->ext_state[id] = module_finished;
|
||||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
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 */
|
/* DNAME to a subdomain loop; do not recurse */
|
||||||
type = RESPONSE_TYPE_ANSWER;
|
type = RESPONSE_TYPE_ANSWER;
|
||||||
}
|
}
|
||||||
} else if(type == RESPONSE_TYPE_CNAME &&
|
}
|
||||||
|
if(type == RESPONSE_TYPE_CNAME &&
|
||||||
iq->qchase.qtype == LDNS_RR_TYPE_CNAME &&
|
iq->qchase.qtype == LDNS_RR_TYPE_CNAME &&
|
||||||
iq->minimisation_state == MINIMISE_STATE &&
|
iq->minimisation_state == MINIMISE_STATE &&
|
||||||
query_dname_compare(iq->qchase.qname, iq->qinfo_out.qname) == 0) {
|
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);
|
return final_state(iq);
|
||||||
} else if(type == RESPONSE_TYPE_REFERRAL) {
|
} else if(type == RESPONSE_TYPE_REFERRAL) {
|
||||||
|
struct delegpt* old_dp = NULL;
|
||||||
/* REFERRAL type responses get a reset of the
|
/* REFERRAL type responses get a reset of the
|
||||||
* delegation point, and back to the QUERYTARGETS_STATE. */
|
* delegation point, and back to the QUERYTARGETS_STATE. */
|
||||||
verbose(VERB_DETAIL, "query response was REFERRAL");
|
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
|
/* Reset the event state, setting the current delegation
|
||||||
* point to the referral. */
|
* point to the referral. */
|
||||||
iq->deleg_msg = iq->response;
|
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);
|
iq->dp = delegpt_from_message(iq->response, qstate->region);
|
||||||
if (qstate->env->cfg->qname_minimisation)
|
if (qstate->env->cfg->qname_minimisation)
|
||||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
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");
|
errinf(qstate, "malloc failure, for delegation point");
|
||||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
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,
|
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
|
||||||
qstate->region, iq->dp)) {
|
qstate->region, iq->dp)) {
|
||||||
errinf(qstate, "malloc failure, copy extra info into delegation point");
|
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 */
|
/* apply rpz qname triggers after cname */
|
||||||
struct dns_msg* forged_response =
|
struct dns_msg* forged_response =
|
||||||
rpz_callback_from_iterator_cname(qstate, iq);
|
rpz_callback_from_iterator_cname(qstate, iq);
|
||||||
|
int count = 0;
|
||||||
while(forged_response && reply_find_rrset_section_an(
|
while(forged_response && reply_find_rrset_section_an(
|
||||||
forged_response->rep, iq->qchase.qname,
|
forged_response->rep, iq->qchase.qname,
|
||||||
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
|
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 */
|
/* another cname to follow */
|
||||||
if(!handle_cname_response(qstate, iq, forged_response,
|
if(!handle_cname_response(qstate, iq, forged_response,
|
||||||
&sname, &snamelen)) {
|
&sname, &snamelen)) {
|
||||||
|
@ -3926,17 +4045,9 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
!qstate->env->cfg->val_log_squelch) {
|
!qstate->env->cfg->val_log_squelch) {
|
||||||
char* err_str = errinf_to_str_misc(qstate);
|
char* err_str = errinf_to_str_misc(qstate);
|
||||||
if(err_str) {
|
if(err_str) {
|
||||||
size_t err_str_len = strlen(err_str);
|
|
||||||
verbose(VERB_ALGO, "iterator EDE: %s", err_str);
|
verbose(VERB_ALGO, "iterator EDE: %s", err_str);
|
||||||
/* allocate space and store the error
|
iq->response->rep->reason_bogus_str = err_str;
|
||||||
* string */
|
|
||||||
iq->response->rep->reason_bogus_str = regional_alloc(
|
|
||||||
qstate->region,
|
|
||||||
sizeof(char) * (err_str_len+1));
|
|
||||||
memcpy(iq->response->rep->reason_bogus_str,
|
|
||||||
err_str, err_str_len+1);
|
|
||||||
}
|
}
|
||||||
free(err_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have finished processing this query */
|
/* we have finished processing this query */
|
||||||
|
|
|
@ -53,6 +53,8 @@
|
||||||
#include "util/storage/slabhash.h"
|
#include "util/storage/slabhash.h"
|
||||||
#include "util/edns.h"
|
#include "util/edns.h"
|
||||||
#include "sldns/sbuffer.h"
|
#include "sldns/sbuffer.h"
|
||||||
|
#include "iterator/iter_fwd.h"
|
||||||
|
#include "iterator/iter_hints.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
context_finalize(struct ub_ctx* ctx)
|
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,
|
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
|
||||||
ctx->env, &ctx->mods))
|
ctx->env, &ctx->mods))
|
||||||
return UB_INITFAIL;
|
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))
|
if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
|
||||||
return UB_INITFAIL;
|
return UB_INITFAIL;
|
||||||
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
|
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
|
||||||
|
|
|
@ -66,6 +66,8 @@
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
#include "services/listen_dnsport.h"
|
#include "services/listen_dnsport.h"
|
||||||
#include "sldns/sbuffer.h"
|
#include "sldns/sbuffer.h"
|
||||||
|
#include "iterator/iter_fwd.h"
|
||||||
|
#include "iterator/iter_hints.h"
|
||||||
#ifdef HAVE_PTHREAD
|
#ifdef HAVE_PTHREAD
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -171,6 +173,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
|
||||||
ctx->env->worker = NULL;
|
ctx->env->worker = NULL;
|
||||||
ctx->env->need_to_validate = 0;
|
ctx->env->need_to_validate = 0;
|
||||||
modstack_init(&ctx->mods);
|
modstack_init(&ctx->mods);
|
||||||
|
ctx->env->modstack = &ctx->mods;
|
||||||
rbtree_init(&ctx->queries, &context_query_cmp);
|
rbtree_init(&ctx->queries, &context_query_cmp);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -379,6 +382,8 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||||
config_delete(ctx->env->cfg);
|
config_delete(ctx->env->cfg);
|
||||||
edns_known_options_delete(ctx->env);
|
edns_known_options_delete(ctx->env);
|
||||||
edns_strings_delete(ctx->env->edns_strings);
|
edns_strings_delete(ctx->env->edns_strings);
|
||||||
|
forwards_delete(ctx->env->fwds);
|
||||||
|
hints_delete(ctx->env->hints);
|
||||||
auth_zones_delete(ctx->env->auth_zones);
|
auth_zones_delete(ctx->env->auth_zones);
|
||||||
free(ctx->env);
|
free(ctx->env);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,6 @@
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
#include "util/data/msgencode.h"
|
#include "util/data/msgencode.h"
|
||||||
#include "util/tube.h"
|
#include "util/tube.h"
|
||||||
#include "iterator/iter_fwd.h"
|
|
||||||
#include "iterator/iter_hints.h"
|
|
||||||
#include "sldns/sbuffer.h"
|
#include "sldns/sbuffer.h"
|
||||||
#include "sldns/str2wire.h"
|
#include "sldns/str2wire.h"
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
|
@ -100,8 +98,6 @@ libworker_delete_env(struct libworker* w)
|
||||||
!w->is_bg || w->is_bg_thread);
|
!w->is_bg || w->is_bg_thread);
|
||||||
sldns_buffer_free(w->env->scratch_buffer);
|
sldns_buffer_free(w->env->scratch_buffer);
|
||||||
regional_destroy(w->env->scratch);
|
regional_destroy(w->env->scratch);
|
||||||
forwards_delete(w->env->fwds);
|
|
||||||
hints_delete(w->env->hints);
|
|
||||||
ub_randfree(w->env->rnd);
|
ub_randfree(w->env->rnd);
|
||||||
free(w->env);
|
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 = regional_create_custom(cfg->msg_buffer_size);
|
||||||
w->env->scratch_buffer = sldns_buffer_new(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
|
#ifdef HAVE_SSL
|
||||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||||
if(!w->sslctx) {
|
if(!w->sslctx) {
|
||||||
/* to make the setup fail after unlock */
|
/* to make the setup fail after unlock */
|
||||||
hints_delete(w->env->hints);
|
sldns_buffer_free(w->env->scratch_buffer);
|
||||||
w->env->hints = NULL;
|
w->env->scratch_buffer = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(!w->is_bg || w->is_bg_thread) {
|
if(!w->is_bg || w->is_bg_thread) {
|
||||||
lock_basic_unlock(&ctx->cfglock);
|
lock_basic_unlock(&ctx->cfglock);
|
||||||
}
|
}
|
||||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
|
if(!w->env->scratch || !w->env->scratch_buffer) {
|
||||||
!w->env->hints) {
|
|
||||||
libworker_delete(w);
|
libworker_delete(w);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2152,6 +2152,16 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
|
||||||
if(az->rpz_first)
|
if(az->rpz_first)
|
||||||
az->rpz_first->rpz_az_prev = z;
|
az->rpz_first->rpz_az_prev = z;
|
||||||
az->rpz_first = 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) {
|
if(c->isrpz) {
|
||||||
lock_rw_unlock(&az->rpz_lock);
|
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);
|
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) */
|
/** find closest NS or DNAME and returns the rrset (locked) */
|
||||||
static struct ub_packed_rrset_key*
|
static struct ub_packed_rrset_key*
|
||||||
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
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
|
/* check for expiry, but we have to let go of the rrset
|
||||||
* for the lock ordering */
|
* for the lock ordering */
|
||||||
lock_rw_unlock(&rrset->entry.lock);
|
lock_rw_unlock(&rrset->entry.lock);
|
||||||
/* the expired_above function always takes off one
|
/* the rrset_cache_expired_above function always takes
|
||||||
* label (if qnamelen>0) and returns the final qname
|
* off one label (if qnamelen>0) and returns the final
|
||||||
* where it searched, so we can continue from there
|
* qname where it searched, so we can continue from
|
||||||
* turning the O N*N search into O N. */
|
* there turning the O N*N search into O N. */
|
||||||
if(!rrset_expired_above(env, &qname, &qnamelen,
|
if(!rrset_cache_expired_above(env->rrset_cache, &qname,
|
||||||
searchtype, qclass, now, expiretop,
|
&qnamelen, searchtype, qclass, now, expiretop,
|
||||||
expiretoplen)) {
|
expiretoplen)) {
|
||||||
/* we want to return rrset, but it may be
|
/* we want to return rrset, but it may be
|
||||||
* gone from cache, if so, just loop like
|
* 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;
|
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*
|
struct infra_cache*
|
||||||
infra_create(struct config_file* cfg)
|
infra_create(struct config_file* cfg)
|
||||||
{
|
{
|
||||||
|
@ -267,6 +342,10 @@ infra_create(struct config_file* cfg)
|
||||||
infra_delete(infra);
|
infra_delete(infra);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if(!setup_wait_limits(infra, cfg)) {
|
||||||
|
infra_delete(infra);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||||
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
|
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
|
||||||
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
|
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
|
void
|
||||||
infra_delete(struct infra_cache* infra)
|
infra_delete(struct infra_cache* infra)
|
||||||
{
|
{
|
||||||
|
@ -296,6 +381,10 @@ infra_delete(struct infra_cache* infra)
|
||||||
slabhash_delete(infra->domain_rates);
|
slabhash_delete(infra->domain_rates);
|
||||||
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
||||||
slabhash_delete(infra->client_ip_rates);
|
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);
|
free(infra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,7 +969,8 @@ static void infra_create_ratedata(struct infra_cache* infra,
|
||||||
|
|
||||||
/** create rate data item for ip address */
|
/** create rate data item for ip address */
|
||||||
static void infra_ip_create_ratedata(struct infra_cache* infra,
|
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);
|
hashvalue_type h = hash_addr(addr, addrlen, 0);
|
||||||
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
|
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;
|
k->entry.data = d;
|
||||||
d->qps[0] = 1;
|
d->qps[0] = 1;
|
||||||
d->timestamp[0] = timenow;
|
d->timestamp[0] = timenow;
|
||||||
|
d->mesh_wait = mesh_wait;
|
||||||
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
|
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 */
|
/* create */
|
||||||
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
|
infra_ip_create_ratedata(infra, addr, addrlen, timenow, 0);
|
||||||
return 1;
|
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;
|
rbtree_type domain_limits;
|
||||||
/** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
|
/** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
|
||||||
struct slabhash* client_ip_rates;
|
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 */
|
/** 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
|
/** what the timestamp is of the qps array members, counter is
|
||||||
* valid for that timestamp. Usually now and now-1. */
|
* valid for that timestamp. Usually now and now-1. */
|
||||||
time_t timestamp[RATE_WINDOW];
|
time_t timestamp[RATE_WINDOW];
|
||||||
|
/** the number of queries waiting in the mesh */
|
||||||
|
int mesh_wait;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ip_rate_data rate_data
|
#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 */
|
/** infra host cache default hash lookup size */
|
||||||
#define INFRA_HOST_STARTSIZE 32
|
#define INFRA_HOST_STARTSIZE 32
|
||||||
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
||||||
|
@ -474,4 +490,16 @@ void ip_rate_delkeyfunc(void* d, void* arg);
|
||||||
/* delete data */
|
/* delete data */
|
||||||
#define ip_rate_deldatafunc rate_deldatafunc
|
#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 */
|
#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/packed_rrset.h"
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
#include "util/data/msgparse.h"
|
#include "util/data/msgparse.h"
|
||||||
|
#include "util/data/dname.h"
|
||||||
#include "util/regional.h"
|
#include "util/regional.h"
|
||||||
#include "util/alloc.h"
|
#include "util/alloc.h"
|
||||||
#include "util/net_help.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* newd = (struct packed_rrset_data*)nd;
|
||||||
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
|
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
|
/* o store if rrset has been validated
|
||||||
* everything better than bogus data
|
* everything better than bogus data
|
||||||
* secure is preferred */
|
* secure is preferred */
|
||||||
|
@ -440,6 +444,89 @@ rrset_check_sec_status(struct rrset_cache* r,
|
||||||
lock_rw_unlock(&e->lock);
|
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,
|
void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
|
||||||
uint16_t type, uint16_t dclass, uint32_t flags)
|
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,
|
void rrset_check_sec_status(struct rrset_cache* r,
|
||||||
struct ub_packed_rrset_key* rrset, time_t now);
|
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
|
* Remove an rrset from the cache, by name and type and flags
|
||||||
* @param r: rrset cache
|
* @param r: rrset cache
|
||||||
|
|
|
@ -140,9 +140,11 @@ void
|
||||||
verbose_print_unbound_socket(struct unbound_socket* ub_sock)
|
verbose_print_unbound_socket(struct unbound_socket* ub_sock)
|
||||||
{
|
{
|
||||||
if(verbosity >= VERB_ALGO) {
|
if(verbosity >= VERB_ALGO) {
|
||||||
|
char buf[256];
|
||||||
log_info("listing of unbound_socket structure:");
|
log_info("listing of unbound_socket structure:");
|
||||||
verbose_print_addr(ub_sock->addr);
|
addr_to_str((void*)ub_sock->addr, ub_sock->addrlen, buf,
|
||||||
log_info("s is: %d, fam is: %s, acl: %s", ub_sock->s,
|
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->fam == AF_INET?"AF_INET":"AF_INET6",
|
||||||
ub_sock->acl?"yes":"no");
|
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__)
|
# elif defined(IP_DONTFRAG) && !defined(__APPLE__)
|
||||||
/* the IP_DONTFRAG option if defined in the 11.0 OSX headers,
|
/* the IP_DONTFRAG option if defined in the 11.0 OSX headers,
|
||||||
* but does not work on that version, so we exclude it */
|
* 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,
|
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
|
||||||
&off, (socklen_t)sizeof(off)) < 0) {
|
&off, (socklen_t)sizeof(off)) < 0) {
|
||||||
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
|
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->s = s;
|
||||||
ub_sock->fam = hints->ai_family;
|
ub_sock->fam = hints->ai_family;
|
||||||
ub_sock->acl = NULL;
|
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,
|
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||||
&noip6, rcv, snd, reuseport, transparent,
|
&noip6, rcv, snd, reuseport, transparent,
|
||||||
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||||
if(ub_sock->addr)
|
free(ub_sock->addr);
|
||||||
freeaddrinfo(ub_sock->addr);
|
|
||||||
free(ub_sock);
|
free(ub_sock);
|
||||||
if(noip6) {
|
if(noip6) {
|
||||||
log_warn("IPv6 protocol not available");
|
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 */
|
/* getting source addr packet info is highly non-portable */
|
||||||
if(!set_recvpktinfo(s, hints->ai_family)) {
|
if(!set_recvpktinfo(s, hints->ai_family)) {
|
||||||
sock_close(s);
|
sock_close(s);
|
||||||
if(ub_sock->addr)
|
free(ub_sock->addr);
|
||||||
freeaddrinfo(ub_sock->addr);
|
|
||||||
free(ub_sock);
|
free(ub_sock);
|
||||||
return 0;
|
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,
|
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
|
||||||
is_pp2, ub_sock)) {
|
is_pp2, ub_sock)) {
|
||||||
sock_close(s);
|
sock_close(s);
|
||||||
if(ub_sock->addr)
|
free(ub_sock->addr);
|
||||||
freeaddrinfo(ub_sock->addr);
|
|
||||||
free(ub_sock);
|
free(ub_sock);
|
||||||
return 0;
|
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,
|
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||||
&noip6, rcv, snd, reuseport, transparent,
|
&noip6, rcv, snd, reuseport, transparent,
|
||||||
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||||
if(ub_sock->addr)
|
free(ub_sock->addr);
|
||||||
freeaddrinfo(ub_sock->addr);
|
|
||||||
free(ub_sock);
|
free(ub_sock);
|
||||||
if(noip6) {
|
if(noip6) {
|
||||||
log_warn("IPv6 protocol not available");
|
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),
|
listen_type_udpancil:listen_type_udp),
|
||||||
is_pp2, ub_sock)) {
|
is_pp2, ub_sock)) {
|
||||||
sock_close(s);
|
sock_close(s);
|
||||||
if(ub_sock->addr)
|
free(ub_sock->addr);
|
||||||
freeaddrinfo(ub_sock->addr);
|
|
||||||
free(ub_sock);
|
free(ub_sock);
|
||||||
return 0;
|
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,
|
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||||
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
|
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
|
||||||
freebind, use_systemd, dscp, ub_sock)) == -1) {
|
freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||||
if(ub_sock->addr)
|
free(ub_sock->addr);
|
||||||
freeaddrinfo(ub_sock->addr);
|
|
||||||
free(ub_sock);
|
free(ub_sock);
|
||||||
if(noip6) {
|
if(noip6) {
|
||||||
/*log_warn("IPv6 protocol not available");*/
|
/*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");
|
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||||
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
|
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
|
||||||
sock_close(s);
|
sock_close(s);
|
||||||
if(ub_sock->addr)
|
free(ub_sock->addr);
|
||||||
freeaddrinfo(ub_sock->addr);
|
|
||||||
free(ub_sock);
|
free(ub_sock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1952,8 +1964,7 @@ void listening_ports_free(struct listen_port* list)
|
||||||
}
|
}
|
||||||
/* rc_ports don't have ub_socket */
|
/* rc_ports don't have ub_socket */
|
||||||
if(list->socket) {
|
if(list->socket) {
|
||||||
if(list->socket->addr)
|
free(list->socket->addr);
|
||||||
freeaddrinfo(list->socket->addr);
|
|
||||||
free(list->socket);
|
free(list->socket);
|
||||||
}
|
}
|
||||||
free(list);
|
free(list);
|
||||||
|
|
|
@ -107,11 +107,13 @@ enum listen_type {
|
||||||
* socket properties (just like NSD nsd_socket structure definition)
|
* socket properties (just like NSD nsd_socket structure definition)
|
||||||
*/
|
*/
|
||||||
struct unbound_socket {
|
struct unbound_socket {
|
||||||
/** socket-address structure */
|
/** the address of the socket */
|
||||||
struct addrinfo* addr;
|
struct sockaddr* addr;
|
||||||
|
/** length of the address */
|
||||||
|
socklen_t addrlen;
|
||||||
/** socket descriptor returned by socket() syscall */
|
/** socket descriptor returned by socket() syscall */
|
||||||
int s;
|
int s;
|
||||||
/** address family (AF_INET/IF_INET6) */
|
/** address family (AF_INET/AF_INET6) */
|
||||||
int fam;
|
int fam;
|
||||||
/** ACL on the socket (listening interface) */
|
/** ACL on the socket (listening interface) */
|
||||||
struct acl_addr* acl;
|
struct acl_addr* acl;
|
||||||
|
|
|
@ -330,14 +330,16 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass,
|
||||||
static struct local_rrset*
|
static struct local_rrset*
|
||||||
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
|
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);
|
type = htons(type);
|
||||||
for(p = data->rrsets; p; p = p->next) {
|
for(p = data->rrsets; p; p = p->next) {
|
||||||
if(p->rrset->rk.type == type)
|
if(p->rrset->rk.type == type)
|
||||||
return p;
|
return p;
|
||||||
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
||||||
return p;
|
cname = p;
|
||||||
}
|
}
|
||||||
|
if(alias_ok)
|
||||||
|
return cname;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "services/outbound_list.h"
|
#include "services/outbound_list.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "services/cache/rrset.h"
|
#include "services/cache/rrset.h"
|
||||||
|
#include "services/cache/infra.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/net_help.h"
|
#include "util/net_help.h"
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
|
@ -385,7 +386,7 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
|
||||||
&mesh_serve_expired_lookup;
|
&mesh_serve_expired_lookup;
|
||||||
|
|
||||||
/* In case this timer already popped, start it again */
|
/* 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.serve_expired_data->timer = comm_timer_create(
|
||||||
mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
|
mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
|
||||||
if(!mstate->s.serve_expired_data->timer)
|
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) {
|
if(rep->c->tcp_req_info) {
|
||||||
r_buffer = rep->c->tcp_req_info->spool_buffer;
|
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)
|
if(!unique)
|
||||||
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||||
/* does this create a new reply state? */
|
/* 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");
|
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||||
goto servfail_mem;
|
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 */
|
/* update statistics */
|
||||||
if(was_detached) {
|
if(was_detached) {
|
||||||
log_assert(mesh->num_detached_states > 0);
|
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);
|
mesh_state_delete(&s->s);
|
||||||
return 0;
|
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 */
|
/* update statistics */
|
||||||
if(was_detached) {
|
if(was_detached) {
|
||||||
log_assert(mesh->num_detached_states > 0);
|
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 */
|
* takes no time and also it does not do the mesh accounting */
|
||||||
mstate->reply_list = NULL;
|
mstate->reply_list = NULL;
|
||||||
for(; rep; rep=rep->next) {
|
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);
|
comm_point_drop_reply(&rep->query_reply);
|
||||||
log_assert(mesh->num_reply_addrs > 0);
|
log_assert(mesh->num_reply_addrs > 0);
|
||||||
mesh->num_reply_addrs--;
|
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;
|
rcode = LDNS_RCODE_SERVFAIL;
|
||||||
if(!rcode && rep && (rep->security == sec_status_bogus ||
|
if(!rcode && rep && (rep->security == sec_status_bogus ||
|
||||||
rep->security == sec_status_secure_sentinel_fail)) {
|
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;
|
rcode = LDNS_RCODE_SERVFAIL;
|
||||||
}
|
}
|
||||||
/* send the reply */
|
/* 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);
|
comm_point_send_reply(&r->query_reply);
|
||||||
m->reply_list = rlist;
|
m->reply_list = rlist;
|
||||||
}
|
}
|
||||||
|
infra_wait_limit_dec(m->s.env->infra_cache, &r->query_reply,
|
||||||
|
m->s.env->cfg);
|
||||||
/* account */
|
/* account */
|
||||||
log_assert(m->s.env->mesh->num_reply_addrs > 0);
|
log_assert(m->s.env->mesh->num_reply_addrs > 0);
|
||||||
m->s.env->mesh->num_reply_addrs--;
|
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,
|
log_reply_info(NO_VERBOSE, &m->s.qinfo,
|
||||||
&r->query_reply.client_addr,
|
&r->query_reply.client_addr,
|
||||||
r->query_reply.client_addrlen, duration, 0, r_buffer,
|
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);
|
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->log_servfail
|
||||||
&& !mstate->s.env->cfg->val_log_squelch) {
|
&& !mstate->s.env->cfg->val_log_squelch) {
|
||||||
char* err = errinf_to_str_servfail(&mstate->s);
|
char* err = errinf_to_str_servfail(&mstate->s);
|
||||||
if(err)
|
if(err) { log_err("%s", err); }
|
||||||
log_err("%s", err);
|
|
||||||
free(err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(r = mstate->reply_list; r; r = r->next) {
|
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++;
|
i++;
|
||||||
tv = r->start_time;
|
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
|
* because the list is NULL and also accounting is not
|
||||||
* done there, but instead we do that here. */
|
* done there, but instead we do that here. */
|
||||||
struct mesh_reply* reply_list = mstate->reply_list;
|
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;
|
mstate->reply_list = NULL;
|
||||||
comm_point_drop_reply(&r->query_reply);
|
comm_point_drop_reply(&r->query_reply);
|
||||||
mstate->reply_list = reply_list;
|
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 */
|
/* delete it, but allocated in m region */
|
||||||
log_assert(mesh->num_reply_addrs > 0);
|
log_assert(mesh->num_reply_addrs > 0);
|
||||||
mesh->num_reply_addrs--;
|
mesh->num_reply_addrs--;
|
||||||
|
infra_wait_limit_dec(mesh->env->infra_cache,
|
||||||
|
&n->query_reply, mesh->env->cfg);
|
||||||
|
|
||||||
/* prev = prev; */
|
/* prev = prev; */
|
||||||
n = n->next;
|
n = n->next;
|
||||||
|
@ -2165,6 +2227,28 @@ mesh_serve_expired_callback(void* arg)
|
||||||
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
||||||
|
|
||||||
for(r = mstate->reply_list; r; r = r->next) {
|
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++;
|
i++;
|
||||||
tv = r->start_time;
|
tv = r->start_time;
|
||||||
|
|
||||||
|
@ -2192,6 +2276,8 @@ mesh_serve_expired_callback(void* arg)
|
||||||
r, r_buffer, prev, prev_buffer);
|
r, r_buffer, prev, prev_buffer);
|
||||||
if(r->query_reply.c->tcp_req_info)
|
if(r->query_reply.c->tcp_req_info)
|
||||||
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
|
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 = r;
|
||||||
prev_buffer = r_buffer;
|
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)
|
int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||||
{
|
{
|
||||||
if(mesh->all.count < mesh->max_reply_states)
|
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);
|
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 */
|
#endif /* SERVICES_MESH_H */
|
||||||
|
|
|
@ -478,6 +478,67 @@ new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
|
||||||
return rrset;
|
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*
|
struct rpz*
|
||||||
rpz_create(struct config_auth* p)
|
rpz_create(struct config_auth* p)
|
||||||
{
|
{
|
||||||
|
@ -513,42 +574,8 @@ rpz_create(struct config_auth* p)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->taglistlen = p->rpz_taglistlen;
|
if(!rpz_apply_cfg_elements(r, p))
|
||||||
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
|
goto err;
|
||||||
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");
|
|
||||||
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;
|
return r;
|
||||||
err:
|
err:
|
||||||
if(r) {
|
if(r) {
|
||||||
|
@ -571,6 +598,32 @@ err:
|
||||||
return NULL;
|
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
|
* Remove RPZ zone name from dname
|
||||||
* Copy dname to newdname, without the originlen number of trailing bytes
|
* 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. */
|
/** Find entry for RR type in the list of rrsets for the clientip. */
|
||||||
static struct local_rrset*
|
static struct local_rrset*
|
||||||
rpz_find_synthesized_rrset(uint16_t qtype,
|
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) {
|
while( cursor != NULL) {
|
||||||
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
|
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
|
||||||
if(htons(qtype) == packed_rrset->type) {
|
if(htons(qtype) == packed_rrset->type) {
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
|
||||||
|
cname = cursor;
|
||||||
cursor = cursor->next;
|
cursor = cursor->next;
|
||||||
}
|
}
|
||||||
|
if(alias_ok)
|
||||||
|
return cname;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,7 +1443,7 @@ static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
|
||||||
struct local_rrset* rrset;
|
struct local_rrset* rrset;
|
||||||
struct packed_rrset_data* d;
|
struct packed_rrset_data* d;
|
||||||
size_t index;
|
size_t index;
|
||||||
rrset = rpz_find_synthesized_rrset(rr_type, node);
|
rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
|
||||||
if(rrset == NULL)
|
if(rrset == NULL)
|
||||||
return 0; /* type not found, ignore */
|
return 0; /* type not found, ignore */
|
||||||
d = (struct packed_rrset_data*)rrset->rrset->entry.data;
|
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 */
|
/* 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) {
|
if(rrset == NULL) {
|
||||||
verbose(VERB_ALGO, "rpz: unable to find local-data for query");
|
verbose(VERB_ALGO, "rpz: unable to find local-data for query");
|
||||||
rrset_count = 0;
|
rrset_count = 0;
|
||||||
|
@ -1823,6 +1880,28 @@ nodata:
|
||||||
rrset_count, rcode, rsoa);
|
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.
|
/** add additional section SOA record to the reply.
|
||||||
* Since this gets fed into the normal iterator answer creation, it
|
* Since this gets fed into the normal iterator answer creation, it
|
||||||
* gets minimal-responses applied to it, that can remove the additional SOA
|
* 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);
|
msg = rpz_dns_msg_new(ms->region);
|
||||||
if(msg == NULL) { return NULL; }
|
if(msg == NULL) { return NULL; }
|
||||||
|
|
||||||
|
msg->qinfo = *qi;
|
||||||
new_reply_info = construct_reply_info_base(ms->region,
|
new_reply_info = construct_reply_info_base(ms->region,
|
||||||
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
||||||
1, /* qd */
|
1, /* qd */
|
||||||
|
@ -1975,40 +2055,42 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
||||||
|
|
||||||
static inline struct dns_msg*
|
static inline struct dns_msg*
|
||||||
rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
|
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;
|
struct local_rrset* rrset;
|
||||||
|
|
||||||
rrset = rpz_find_synthesized_rrset(qi->qtype, data);
|
rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
|
||||||
if(rrset == NULL) {
|
if(rrset == NULL) {
|
||||||
verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
|
verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
|
||||||
return NULL;
|
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 */
|
/* copy'n'paste from localzone.c */
|
||||||
static struct local_rrset*
|
static struct local_rrset*
|
||||||
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
|
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);
|
type = htons(type);
|
||||||
for(p = data->rrsets; p; p = p->next) {
|
for(p = data->rrsets; p; p = p->next) {
|
||||||
if(p->rrset->rk.type == type)
|
if(p->rrset->rk.type == type)
|
||||||
return p;
|
return p;
|
||||||
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
||||||
return p;
|
cname = p;
|
||||||
}
|
}
|
||||||
|
if(alias_ok)
|
||||||
|
return cname;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* based on localzone.c:local_data_answer() */
|
/* based on localzone.c:local_data_answer() */
|
||||||
static inline struct dns_msg*
|
static inline struct dns_msg*
|
||||||
rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
|
rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
|
||||||
struct local_zone* z, struct matched_delegation_point const* match,
|
struct query_info* qi, struct local_zone* z,
|
||||||
struct auth_zone* az)
|
struct matched_delegation_point const* match, struct auth_zone* az)
|
||||||
{
|
{
|
||||||
struct local_data key;
|
struct local_data key;
|
||||||
struct local_data* ld;
|
struct local_data* ld;
|
||||||
|
@ -2029,13 +2111,13 @@ rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rrset = local_data_find_type(ld, ms->qinfo.qtype, 1);
|
rrset = local_data_find_type(ld, qi->qtype, 1);
|
||||||
if(rrset == NULL) {
|
if(rrset == NULL) {
|
||||||
verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
|
verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
|
||||||
return NULL;
|
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 */
|
/* 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);
|
key.namelabs = dname_count_labels(qinfo->qname);
|
||||||
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
|
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
|
||||||
if(ld == NULL) {
|
if(ld == NULL) {
|
||||||
verbose(VERB_ALGO, "rpz: qname after cname: name not found");
|
verbose(VERB_ALGO, "rpz: qname: name not found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
rrset = local_data_find_type(ld, qinfo->qtype, 1);
|
rrset = local_data_find_type(ld, qinfo->qtype, 1);
|
||||||
if(rrset == NULL) {
|
if(rrset == NULL) {
|
||||||
verbose(VERB_ALGO, "rpz: qname after cname: type not found");
|
verbose(VERB_ALGO, "rpz: qname: type not found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
|
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
|
static int
|
||||||
rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
||||||
struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
|
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;
|
struct local_data* ld = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||||
qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset));
|
if(!rpz_apply_cname_override_action(r, qinfo, temp))
|
||||||
if(qinfo->local_alias == NULL) {
|
return 0;
|
||||||
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(r->log) {
|
if(r->log) {
|
||||||
log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
|
log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
|
||||||
qinfo, repinfo, NULL, r->log_name);
|
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*
|
static struct dns_msg*
|
||||||
rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||||
struct clientip_synthesized_rr* raddr, struct auth_zone* az)
|
struct rpz* r, struct clientip_synthesized_rr* raddr,
|
||||||
|
struct auth_zone* az)
|
||||||
{
|
{
|
||||||
enum rpz_action action = raddr->action;
|
enum rpz_action action = raddr->action;
|
||||||
struct dns_msg* ret = NULL;
|
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) {
|
if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
|
||||||
verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
|
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;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(action) {
|
switch(action) {
|
||||||
case RPZ_NXDOMAIN_ACTION:
|
case RPZ_NXDOMAIN_ACTION:
|
||||||
ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
|
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||||
break;
|
break;
|
||||||
case RPZ_NODATA_ACTION:
|
case RPZ_NODATA_ACTION:
|
||||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||||
break;
|
break;
|
||||||
case RPZ_TCP_ONLY_ACTION:
|
case RPZ_TCP_ONLY_ACTION:
|
||||||
/* basically a passthru here but the tcp-only will be
|
/* 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;
|
ret = NULL;
|
||||||
break;
|
break;
|
||||||
case RPZ_DROP_ACTION:
|
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;
|
ms->is_drop = 1;
|
||||||
break;
|
break;
|
||||||
case RPZ_LOCAL_DATA_ACTION:
|
case RPZ_LOCAL_DATA_ACTION:
|
||||||
ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az);
|
ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
|
||||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
|
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
|
||||||
break;
|
break;
|
||||||
case RPZ_PASSTHRU_ACTION:
|
case RPZ_PASSTHRU_ACTION:
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
ms->rpz_passthru = 1;
|
ms->rpz_passthru = 1;
|
||||||
break;
|
break;
|
||||||
|
case RPZ_CNAME_OVERRIDE_ACTION:
|
||||||
|
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
|
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
|
||||||
rpz_action_to_string(action));
|
rpz_action_to_string(action));
|
||||||
|
@ -2194,9 +2324,9 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dns_msg*
|
static struct dns_msg*
|
||||||
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||||
struct local_zone* z, struct matched_delegation_point const* match,
|
struct rpz* r, struct local_zone* z,
|
||||||
struct auth_zone* az)
|
struct matched_delegation_point const* match, struct auth_zone* az)
|
||||||
{
|
{
|
||||||
struct dns_msg* ret = NULL;
|
struct dns_msg* ret = NULL;
|
||||||
enum rpz_action action = localzone_type_to_rpz_action(z->type);
|
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) {
|
switch(action) {
|
||||||
case RPZ_NXDOMAIN_ACTION:
|
case RPZ_NXDOMAIN_ACTION:
|
||||||
ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
|
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||||
break;
|
break;
|
||||||
case RPZ_NODATA_ACTION:
|
case RPZ_NODATA_ACTION:
|
||||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||||
break;
|
break;
|
||||||
case RPZ_TCP_ONLY_ACTION:
|
case RPZ_TCP_ONLY_ACTION:
|
||||||
/* basically a passthru here but the tcp-only will be
|
/* 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;
|
ret = NULL;
|
||||||
break;
|
break;
|
||||||
case RPZ_DROP_ACTION:
|
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;
|
ms->is_drop = 1;
|
||||||
break;
|
break;
|
||||||
case RPZ_LOCAL_DATA_ACTION:
|
case RPZ_LOCAL_DATA_ACTION:
|
||||||
ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az);
|
ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
|
||||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
|
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
|
||||||
break;
|
break;
|
||||||
case RPZ_PASSTHRU_ACTION:
|
case RPZ_PASSTHRU_ACTION:
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
ms->rpz_passthru = 1;
|
ms->rpz_passthru = 1;
|
||||||
break;
|
break;
|
||||||
|
case RPZ_CNAME_OVERRIDE_ACTION:
|
||||||
|
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
|
||||||
|
break;
|
||||||
default:
|
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));
|
rpz_action_to_string(action));
|
||||||
ret = NULL;
|
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 */
|
/* the nsdname has precedence over the nsip triggers */
|
||||||
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
|
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
|
||||||
ms->qinfo.qclass, &match);
|
is->qchase.qclass, &match);
|
||||||
if(z != NULL) {
|
if(z != NULL) {
|
||||||
lock_rw_unlock(&a->lock);
|
lock_rw_unlock(&a->lock);
|
||||||
break;
|
break;
|
||||||
|
@ -2347,9 +2480,9 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
||||||
if(z) {
|
if(z) {
|
||||||
lock_rw_unlock(&z->lock);
|
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,
|
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(is->qchase.qname, nm);
|
||||||
dname_str(z->name, zn);
|
dname_str(z->name, zn);
|
||||||
if(strcmp(zn, nm) != 0)
|
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)));
|
zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||||
else
|
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)));
|
nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||||
}
|
}
|
||||||
switch(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;
|
ms->rpz_passthru = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
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)));
|
rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||||
ret = NULL;
|
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);
|
az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
|
||||||
|
|
||||||
client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
|
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(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;
|
*passthru = 1;
|
||||||
|
ret = 0;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
|
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
|
||||||
client_action != RPZ_PASSTHRU_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) {
|
if(client_action == RPZ_LOCAL_DATA_ACTION) {
|
||||||
rpz_apply_clientip_localdata_action(node, env, qinfo,
|
rpz_apply_clientip_localdata_action(node, env, qinfo,
|
||||||
edns, repinfo, buf, temp, *a_out);
|
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 {
|
} 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,
|
local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
|
||||||
repinfo, buf, temp, 0 /* no local data used */,
|
repinfo, buf, temp, 0 /* no local data used */,
|
||||||
rpz_action_to_localzone_type(client_action));
|
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_WIRE(sldns_buffer_begin(buf))
|
||||||
== LDNS_RCODE_NXDOMAIN)
|
== LDNS_RCODE_NXDOMAIN)
|
||||||
LDNS_RA_CLR(sldns_buffer_begin(buf));
|
LDNS_RA_CLR(sldns_buffer_begin(buf));
|
||||||
|
ret = 1;
|
||||||
}
|
}
|
||||||
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;
|
goto done;
|
||||||
}
|
}
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
|
@ -225,6 +225,14 @@ int rpz_clear(struct rpz* r);
|
||||||
*/
|
*/
|
||||||
struct rpz* rpz_create(struct config_auth* p);
|
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
|
* String for RPZ action enum
|
||||||
* @param a: RPZ action to get string for
|
* @param a: RPZ action to get string for
|
||||||
|
|
|
@ -126,7 +126,8 @@ void view_delete(struct view* v);
|
||||||
*/
|
*/
|
||||||
void views_print(struct views* v);
|
void views_print(struct views* v);
|
||||||
|
|
||||||
/* Find a view by name.
|
/**
|
||||||
|
* Find a view by name.
|
||||||
* @param vs: views
|
* @param vs: views
|
||||||
* @param name: name of the view we are looking for
|
* @param name: name of the view we are looking for
|
||||||
* @param write: 1 for obtaining write lock on found view, 0 for read lock
|
* @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->min_ttl = 0;
|
||||||
cfg->max_ttl = 3600 * 24;
|
cfg->max_ttl = 3600 * 24;
|
||||||
cfg->max_negative_ttl = 3600;
|
cfg->max_negative_ttl = 3600;
|
||||||
|
cfg->min_negative_ttl = 0;
|
||||||
cfg->prefetch = 0;
|
cfg->prefetch = 0;
|
||||||
cfg->prefetch_key = 0;
|
cfg->prefetch_key = 0;
|
||||||
cfg->deny_any = 0;
|
cfg->deny_any = 0;
|
||||||
|
@ -308,6 +309,11 @@ config_create(void)
|
||||||
cfg->minimal_responses = 1;
|
cfg->minimal_responses = 1;
|
||||||
cfg->rrset_roundrobin = 1;
|
cfg->rrset_roundrobin = 1;
|
||||||
cfg->unknown_server_time_limit = 376;
|
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 */
|
cfg->max_udp_size = 1232; /* value taken from edns_buffer_size */
|
||||||
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
|
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
@ -384,6 +390,7 @@ config_create(void)
|
||||||
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
|
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
|
||||||
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
|
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
|
||||||
cfg->cachedb_no_store = 0;
|
cfg->cachedb_no_store = 0;
|
||||||
|
cfg->cachedb_check_when_serve_expired = 1;
|
||||||
#ifdef USE_REDIS
|
#ifdef USE_REDIS
|
||||||
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
|
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
|
||||||
cfg->redis_server_path = NULL;
|
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;}
|
{ 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)
|
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;}
|
{ 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)
|
else if(strcmp(opt, "cache-min-ttl:") == 0)
|
||||||
{ IS_NUMBER_OR_ZERO; cfg->min_ttl = atoi(val); MIN_TTL=(time_t)cfg->min_ttl;}
|
{ 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) {
|
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("minimal-responses:", minimal_responses)
|
||||||
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
|
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("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_STRLIST("local-data:", local_data)
|
||||||
else S_YNO("unblock-lan-zones:", unblock_lan_zones)
|
else S_YNO("unblock-lan-zones:", unblock_lan_zones)
|
||||||
else S_YNO("insecure-lan-zones:", insecure_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
|
#endif
|
||||||
#ifdef USE_CACHEDB
|
#ifdef USE_CACHEDB
|
||||||
else S_YNO("cachedb-no-store:", cachedb_no_store)
|
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 */
|
#endif /* USE_CACHEDB */
|
||||||
else if(strcmp(opt, "define-tag:") ==0) {
|
else if(strcmp(opt, "define-tag:") ==0) {
|
||||||
return config_add_tag(cfg, val);
|
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_YNO(opt, "deny-any", deny_any)
|
||||||
else O_DEC(opt, "cache-max-ttl", max_ttl)
|
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-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, "cache-min-ttl", min_ttl)
|
||||||
else O_DEC(opt, "infra-host-ttl", host_ttl)
|
else O_DEC(opt, "infra-host-ttl", host_ttl)
|
||||||
else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs)
|
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, "minimal-responses", minimal_responses)
|
||||||
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
|
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
|
||||||
else O_DEC(opt, "unknown-server-time-limit", unknown_server_time_limit)
|
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
|
#ifdef CLIENT_SUBNET
|
||||||
else O_LST(opt, "send-client-subnet", client_subnet)
|
else O_LST(opt, "send-client-subnet", client_subnet)
|
||||||
else O_LST(opt, "client-subnet-zone", client_subnet_zone)
|
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, "backend", cachedb_backend)
|
||||||
else O_STR(opt, "secret-seed", cachedb_secret)
|
else O_STR(opt, "secret-seed", cachedb_secret)
|
||||||
else O_YNO(opt, "cachedb-no-store", cachedb_no_store)
|
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
|
#ifdef USE_REDIS
|
||||||
else O_STR(opt, "redis-server-host", redis_server_host)
|
else O_STR(opt, "redis-server-host", redis_server_host)
|
||||||
else O_DEC(opt, "redis-server-port", redis_server_port)
|
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_actions);
|
||||||
config_deltrplstrlist(cfg->interface_tag_datas);
|
config_deltrplstrlist(cfg->interface_tag_datas);
|
||||||
config_delstrlist(cfg->control_ifs.first);
|
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_key_file);
|
||||||
free(cfg->server_cert_file);
|
free(cfg->server_cert_file);
|
||||||
free(cfg->control_key_file);
|
free(cfg->control_key_file);
|
||||||
|
@ -1761,6 +1783,10 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
|
||||||
#endif
|
#endif
|
||||||
if(!mid) {
|
if(!mid) {
|
||||||
int port = atoi(str);
|
int port = atoi(str);
|
||||||
|
if(port < 0) {
|
||||||
|
log_err("port number is negative: %d", port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if(port == 0 && strcmp(str, "0") != 0) {
|
if(port == 0 && strcmp(str, "0") != 0) {
|
||||||
log_err("cannot parse port number '%s'", str);
|
log_err("cannot parse port number '%s'", str);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1770,6 +1796,10 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
|
||||||
} else {
|
} else {
|
||||||
int i, low, high = atoi(mid+1);
|
int i, low, high = atoi(mid+1);
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
if(high < 0) {
|
||||||
|
log_err("port number is negative: %d", high);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if(high == 0 && strcmp(mid+1, "0") != 0) {
|
if(high == 0 && strcmp(mid+1, "0") != 0) {
|
||||||
log_err("cannot parse port number '%s'", mid+1);
|
log_err("cannot parse port number '%s'", mid+1);
|
||||||
return 0;
|
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));
|
memcpy(buf, str, (size_t)(mid-str));
|
||||||
buf[mid-str] = 0;
|
buf[mid-str] = 0;
|
||||||
low = atoi(buf);
|
low = atoi(buf);
|
||||||
|
if(low < 0) {
|
||||||
|
log_err("port number is negative: %d", low);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if(low == 0 && strcmp(buf, "0") != 0) {
|
if(low == 0 && strcmp(buf, "0") != 0) {
|
||||||
log_err("cannot parse port number '%s'", buf);
|
log_err("cannot parse port number '%s'", buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(high > num) {
|
||||||
|
/* Stop very high values from taking a long time. */
|
||||||
|
high = num;
|
||||||
|
}
|
||||||
for(i=low; i<=high; i++) {
|
for(i=low; i<=high; i++) {
|
||||||
if(i < num)
|
if(i < num)
|
||||||
avail[i] = (allow?i:0);
|
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_EXPIRED_REPLY_TTL = (time_t)config->serve_expired_reply_ttl;
|
||||||
SERVE_ORIGINAL_TTL = config->serve_original_ttl;
|
SERVE_ORIGINAL_TTL = config->serve_original_ttl;
|
||||||
MAX_NEG_TTL = (time_t)config->max_negative_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_MIN_TIMEOUT = config->infra_cache_min_rtt;
|
||||||
RTT_MAX_TIMEOUT = config->infra_cache_max_rtt;
|
RTT_MAX_TIMEOUT = config->infra_cache_max_rtt;
|
||||||
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
|
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
|
||||||
|
|
|
@ -315,6 +315,8 @@ struct config_file {
|
||||||
int min_ttl;
|
int min_ttl;
|
||||||
/** the number of seconds maximal negative TTL for SOA in auth */
|
/** the number of seconds maximal negative TTL for SOA in auth */
|
||||||
int max_negative_ttl;
|
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. */
|
/** if prefetching of messages should be performed. */
|
||||||
int prefetch;
|
int prefetch;
|
||||||
/** if prefetching of DNSKEYs should be performed. */
|
/** if prefetching of DNSKEYs should be performed. */
|
||||||
|
@ -535,6 +537,21 @@ struct config_file {
|
||||||
/* wait time for unknown server in msec */
|
/* wait time for unknown server in msec */
|
||||||
int unknown_server_time_limit;
|
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 */
|
/* maximum UDP response size */
|
||||||
size_t max_udp_size;
|
size_t max_udp_size;
|
||||||
|
|
||||||
|
@ -705,6 +722,8 @@ struct config_file {
|
||||||
char* cachedb_secret;
|
char* cachedb_secret;
|
||||||
/** cachedb that does not store, but only reads from database, if on */
|
/** cachedb that does not store, but only reads from database, if on */
|
||||||
int cachedb_no_store;
|
int cachedb_no_store;
|
||||||
|
/** cachedb check before serving serve-expired response */
|
||||||
|
int cachedb_check_when_serve_expired;
|
||||||
#ifdef USE_REDIS
|
#ifdef USE_REDIS
|
||||||
/** redis server's IP address or host name */
|
/** redis server's IP address or host name */
|
||||||
char* redis_server_host;
|
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) }
|
rrset-cache-slabs{COLON} { YDVAR(1, VAR_RRSET_CACHE_SLABS) }
|
||||||
cache-max-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_TTL) }
|
cache-max-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_TTL) }
|
||||||
cache-max-negative-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_NEGATIVE_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) }
|
cache-min-ttl{COLON} { YDVAR(1, VAR_CACHE_MIN_TTL) }
|
||||||
infra-host-ttl{COLON} { YDVAR(1, VAR_INFRA_HOST_TTL) }
|
infra-host-ttl{COLON} { YDVAR(1, VAR_INFRA_HOST_TTL) }
|
||||||
infra-lame-ttl{COLON} { YDVAR(1, VAR_INFRA_LAME_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) }
|
minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) }
|
||||||
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
|
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
|
||||||
unknown-server-time-limit{COLON} { YDVAR(1, VAR_UNKNOWN_SERVER_TIME_LIMIT) }
|
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) }
|
max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) }
|
||||||
dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
|
dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
|
||||||
dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) }
|
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) }
|
backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
|
||||||
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
|
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
|
||||||
cachedb-no-store{COLON} { YDVAR(1, VAR_CACHEDB_NO_STORE) }
|
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-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
|
||||||
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
|
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
|
||||||
redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }
|
redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }
|
||||||
|
|
|
@ -222,129 +222,136 @@
|
||||||
#define VAR_CAPS_WHITELIST 478
|
#define VAR_CAPS_WHITELIST 478
|
||||||
#define VAR_CACHE_MAX_NEGATIVE_TTL 479
|
#define VAR_CACHE_MAX_NEGATIVE_TTL 479
|
||||||
#define VAR_PERMIT_SMALL_HOLDDOWN 480
|
#define VAR_PERMIT_SMALL_HOLDDOWN 480
|
||||||
#define VAR_QNAME_MINIMISATION 481
|
#define VAR_CACHE_MIN_NEGATIVE_TTL 481
|
||||||
#define VAR_QNAME_MINIMISATION_STRICT 482
|
#define VAR_QNAME_MINIMISATION 482
|
||||||
#define VAR_IP_FREEBIND 483
|
#define VAR_QNAME_MINIMISATION_STRICT 483
|
||||||
#define VAR_DEFINE_TAG 484
|
#define VAR_IP_FREEBIND 484
|
||||||
#define VAR_LOCAL_ZONE_TAG 485
|
#define VAR_DEFINE_TAG 485
|
||||||
#define VAR_ACCESS_CONTROL_TAG 486
|
#define VAR_LOCAL_ZONE_TAG 486
|
||||||
#define VAR_LOCAL_ZONE_OVERRIDE 487
|
#define VAR_ACCESS_CONTROL_TAG 487
|
||||||
#define VAR_ACCESS_CONTROL_TAG_ACTION 488
|
#define VAR_LOCAL_ZONE_OVERRIDE 488
|
||||||
#define VAR_ACCESS_CONTROL_TAG_DATA 489
|
#define VAR_ACCESS_CONTROL_TAG_ACTION 489
|
||||||
#define VAR_VIEW 490
|
#define VAR_ACCESS_CONTROL_TAG_DATA 490
|
||||||
#define VAR_ACCESS_CONTROL_VIEW 491
|
#define VAR_VIEW 491
|
||||||
#define VAR_VIEW_FIRST 492
|
#define VAR_ACCESS_CONTROL_VIEW 492
|
||||||
#define VAR_SERVE_EXPIRED 493
|
#define VAR_VIEW_FIRST 493
|
||||||
#define VAR_SERVE_EXPIRED_TTL 494
|
#define VAR_SERVE_EXPIRED 494
|
||||||
#define VAR_SERVE_EXPIRED_TTL_RESET 495
|
#define VAR_SERVE_EXPIRED_TTL 495
|
||||||
#define VAR_SERVE_EXPIRED_REPLY_TTL 496
|
#define VAR_SERVE_EXPIRED_TTL_RESET 496
|
||||||
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 497
|
#define VAR_SERVE_EXPIRED_REPLY_TTL 497
|
||||||
#define VAR_EDE_SERVE_EXPIRED 498
|
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 498
|
||||||
#define VAR_SERVE_ORIGINAL_TTL 499
|
#define VAR_EDE_SERVE_EXPIRED 499
|
||||||
#define VAR_FAKE_DSA 500
|
#define VAR_SERVE_ORIGINAL_TTL 500
|
||||||
#define VAR_FAKE_SHA1 501
|
#define VAR_FAKE_DSA 501
|
||||||
#define VAR_LOG_IDENTITY 502
|
#define VAR_FAKE_SHA1 502
|
||||||
#define VAR_HIDE_TRUSTANCHOR 503
|
#define VAR_LOG_IDENTITY 503
|
||||||
#define VAR_HIDE_HTTP_USER_AGENT 504
|
#define VAR_HIDE_TRUSTANCHOR 504
|
||||||
#define VAR_HTTP_USER_AGENT 505
|
#define VAR_HIDE_HTTP_USER_AGENT 505
|
||||||
#define VAR_TRUST_ANCHOR_SIGNALING 506
|
#define VAR_HTTP_USER_AGENT 506
|
||||||
#define VAR_AGGRESSIVE_NSEC 507
|
#define VAR_TRUST_ANCHOR_SIGNALING 507
|
||||||
#define VAR_USE_SYSTEMD 508
|
#define VAR_AGGRESSIVE_NSEC 508
|
||||||
#define VAR_SHM_ENABLE 509
|
#define VAR_USE_SYSTEMD 509
|
||||||
#define VAR_SHM_KEY 510
|
#define VAR_SHM_ENABLE 510
|
||||||
#define VAR_ROOT_KEY_SENTINEL 511
|
#define VAR_SHM_KEY 511
|
||||||
#define VAR_DNSCRYPT 512
|
#define VAR_ROOT_KEY_SENTINEL 512
|
||||||
#define VAR_DNSCRYPT_ENABLE 513
|
#define VAR_DNSCRYPT 513
|
||||||
#define VAR_DNSCRYPT_PORT 514
|
#define VAR_DNSCRYPT_ENABLE 514
|
||||||
#define VAR_DNSCRYPT_PROVIDER 515
|
#define VAR_DNSCRYPT_PORT 515
|
||||||
#define VAR_DNSCRYPT_SECRET_KEY 516
|
#define VAR_DNSCRYPT_PROVIDER 516
|
||||||
#define VAR_DNSCRYPT_PROVIDER_CERT 517
|
#define VAR_DNSCRYPT_SECRET_KEY 517
|
||||||
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 518
|
#define VAR_DNSCRYPT_PROVIDER_CERT 518
|
||||||
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 519
|
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 519
|
||||||
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 520
|
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 520
|
||||||
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 521
|
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 521
|
||||||
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 522
|
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 522
|
||||||
#define VAR_PAD_RESPONSES 523
|
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 523
|
||||||
#define VAR_PAD_RESPONSES_BLOCK_SIZE 524
|
#define VAR_PAD_RESPONSES 524
|
||||||
#define VAR_PAD_QUERIES 525
|
#define VAR_PAD_RESPONSES_BLOCK_SIZE 525
|
||||||
#define VAR_PAD_QUERIES_BLOCK_SIZE 526
|
#define VAR_PAD_QUERIES 526
|
||||||
#define VAR_IPSECMOD_ENABLED 527
|
#define VAR_PAD_QUERIES_BLOCK_SIZE 527
|
||||||
#define VAR_IPSECMOD_HOOK 528
|
#define VAR_IPSECMOD_ENABLED 528
|
||||||
#define VAR_IPSECMOD_IGNORE_BOGUS 529
|
#define VAR_IPSECMOD_HOOK 529
|
||||||
#define VAR_IPSECMOD_MAX_TTL 530
|
#define VAR_IPSECMOD_IGNORE_BOGUS 530
|
||||||
#define VAR_IPSECMOD_WHITELIST 531
|
#define VAR_IPSECMOD_MAX_TTL 531
|
||||||
#define VAR_IPSECMOD_STRICT 532
|
#define VAR_IPSECMOD_WHITELIST 532
|
||||||
#define VAR_CACHEDB 533
|
#define VAR_IPSECMOD_STRICT 533
|
||||||
#define VAR_CACHEDB_BACKEND 534
|
#define VAR_CACHEDB 534
|
||||||
#define VAR_CACHEDB_SECRETSEED 535
|
#define VAR_CACHEDB_BACKEND 535
|
||||||
#define VAR_CACHEDB_REDISHOST 536
|
#define VAR_CACHEDB_SECRETSEED 536
|
||||||
#define VAR_CACHEDB_REDISPORT 537
|
#define VAR_CACHEDB_REDISHOST 537
|
||||||
#define VAR_CACHEDB_REDISTIMEOUT 538
|
#define VAR_CACHEDB_REDISPORT 538
|
||||||
#define VAR_CACHEDB_REDISEXPIRERECORDS 539
|
#define VAR_CACHEDB_REDISTIMEOUT 539
|
||||||
#define VAR_CACHEDB_REDISPATH 540
|
#define VAR_CACHEDB_REDISEXPIRERECORDS 540
|
||||||
#define VAR_CACHEDB_REDISPASSWORD 541
|
#define VAR_CACHEDB_REDISPATH 541
|
||||||
#define VAR_CACHEDB_REDISLOGICALDB 542
|
#define VAR_CACHEDB_REDISPASSWORD 542
|
||||||
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 543
|
#define VAR_CACHEDB_REDISLOGICALDB 543
|
||||||
#define VAR_FOR_UPSTREAM 544
|
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 544
|
||||||
#define VAR_AUTH_ZONE 545
|
#define VAR_FOR_UPSTREAM 545
|
||||||
#define VAR_ZONEFILE 546
|
#define VAR_AUTH_ZONE 546
|
||||||
#define VAR_MASTER 547
|
#define VAR_ZONEFILE 547
|
||||||
#define VAR_URL 548
|
#define VAR_MASTER 548
|
||||||
#define VAR_FOR_DOWNSTREAM 549
|
#define VAR_URL 549
|
||||||
#define VAR_FALLBACK_ENABLED 550
|
#define VAR_FOR_DOWNSTREAM 550
|
||||||
#define VAR_TLS_ADDITIONAL_PORT 551
|
#define VAR_FALLBACK_ENABLED 551
|
||||||
#define VAR_LOW_RTT 552
|
#define VAR_TLS_ADDITIONAL_PORT 552
|
||||||
#define VAR_LOW_RTT_PERMIL 553
|
#define VAR_LOW_RTT 553
|
||||||
#define VAR_FAST_SERVER_PERMIL 554
|
#define VAR_LOW_RTT_PERMIL 554
|
||||||
#define VAR_FAST_SERVER_NUM 555
|
#define VAR_FAST_SERVER_PERMIL 555
|
||||||
#define VAR_ALLOW_NOTIFY 556
|
#define VAR_FAST_SERVER_NUM 556
|
||||||
#define VAR_TLS_WIN_CERT 557
|
#define VAR_ALLOW_NOTIFY 557
|
||||||
#define VAR_TCP_CONNECTION_LIMIT 558
|
#define VAR_TLS_WIN_CERT 558
|
||||||
#define VAR_ANSWER_COOKIE 559
|
#define VAR_TCP_CONNECTION_LIMIT 559
|
||||||
#define VAR_COOKIE_SECRET 560
|
#define VAR_ANSWER_COOKIE 560
|
||||||
#define VAR_IP_RATELIMIT_COOKIE 561
|
#define VAR_COOKIE_SECRET 561
|
||||||
#define VAR_FORWARD_NO_CACHE 562
|
#define VAR_IP_RATELIMIT_COOKIE 562
|
||||||
#define VAR_STUB_NO_CACHE 563
|
#define VAR_FORWARD_NO_CACHE 563
|
||||||
#define VAR_LOG_SERVFAIL 564
|
#define VAR_STUB_NO_CACHE 564
|
||||||
#define VAR_DENY_ANY 565
|
#define VAR_LOG_SERVFAIL 565
|
||||||
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 566
|
#define VAR_DENY_ANY 566
|
||||||
#define VAR_LOG_TAG_QUERYREPLY 567
|
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 567
|
||||||
#define VAR_STREAM_WAIT_SIZE 568
|
#define VAR_LOG_TAG_QUERYREPLY 568
|
||||||
#define VAR_TLS_CIPHERS 569
|
#define VAR_DISCARD_TIMEOUT 569
|
||||||
#define VAR_TLS_CIPHERSUITES 570
|
#define VAR_WAIT_LIMIT 570
|
||||||
#define VAR_TLS_USE_SNI 571
|
#define VAR_WAIT_LIMIT_COOKIE 571
|
||||||
#define VAR_IPSET 572
|
#define VAR_WAIT_LIMIT_NETBLOCK 572
|
||||||
#define VAR_IPSET_NAME_V4 573
|
#define VAR_WAIT_LIMIT_COOKIE_NETBLOCK 573
|
||||||
#define VAR_IPSET_NAME_V6 574
|
#define VAR_STREAM_WAIT_SIZE 574
|
||||||
#define VAR_TLS_SESSION_TICKET_KEYS 575
|
#define VAR_TLS_CIPHERS 575
|
||||||
#define VAR_RPZ 576
|
#define VAR_TLS_CIPHERSUITES 576
|
||||||
#define VAR_TAGS 577
|
#define VAR_TLS_USE_SNI 577
|
||||||
#define VAR_RPZ_ACTION_OVERRIDE 578
|
#define VAR_IPSET 578
|
||||||
#define VAR_RPZ_CNAME_OVERRIDE 579
|
#define VAR_IPSET_NAME_V4 579
|
||||||
#define VAR_RPZ_LOG 580
|
#define VAR_IPSET_NAME_V6 580
|
||||||
#define VAR_RPZ_LOG_NAME 581
|
#define VAR_TLS_SESSION_TICKET_KEYS 581
|
||||||
#define VAR_DYNLIB 582
|
#define VAR_RPZ 582
|
||||||
#define VAR_DYNLIB_FILE 583
|
#define VAR_TAGS 583
|
||||||
#define VAR_EDNS_CLIENT_STRING 584
|
#define VAR_RPZ_ACTION_OVERRIDE 584
|
||||||
#define VAR_EDNS_CLIENT_STRING_OPCODE 585
|
#define VAR_RPZ_CNAME_OVERRIDE 585
|
||||||
#define VAR_NSID 586
|
#define VAR_RPZ_LOG 586
|
||||||
#define VAR_ZONEMD_PERMISSIVE_MODE 587
|
#define VAR_RPZ_LOG_NAME 587
|
||||||
#define VAR_ZONEMD_CHECK 588
|
#define VAR_DYNLIB 588
|
||||||
#define VAR_ZONEMD_REJECT_ABSENCE 589
|
#define VAR_DYNLIB_FILE 589
|
||||||
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 590
|
#define VAR_EDNS_CLIENT_STRING 590
|
||||||
#define VAR_INTERFACE_AUTOMATIC_PORTS 591
|
#define VAR_EDNS_CLIENT_STRING_OPCODE 591
|
||||||
#define VAR_EDE 592
|
#define VAR_NSID 592
|
||||||
#define VAR_INTERFACE_ACTION 593
|
#define VAR_ZONEMD_PERMISSIVE_MODE 593
|
||||||
#define VAR_INTERFACE_VIEW 594
|
#define VAR_ZONEMD_CHECK 594
|
||||||
#define VAR_INTERFACE_TAG 595
|
#define VAR_ZONEMD_REJECT_ABSENCE 595
|
||||||
#define VAR_INTERFACE_TAG_ACTION 596
|
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 596
|
||||||
#define VAR_INTERFACE_TAG_DATA 597
|
#define VAR_INTERFACE_AUTOMATIC_PORTS 597
|
||||||
#define VAR_PROXY_PROTOCOL_PORT 598
|
#define VAR_EDE 598
|
||||||
#define VAR_STATISTICS_INHIBIT_ZERO 599
|
#define VAR_INTERFACE_ACTION 599
|
||||||
#define VAR_HARDEN_UNKNOWN_ADDITIONAL 600
|
#define VAR_INTERFACE_VIEW 600
|
||||||
#define VAR_DISABLE_EDNS_DO 601
|
#define VAR_INTERFACE_TAG 601
|
||||||
#define VAR_CACHEDB_NO_STORE 602
|
#define VAR_INTERFACE_TAG_ACTION 602
|
||||||
#define VAR_LOG_DESTADDR 603
|
#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
|
#ifndef YYSTYPE_DEFINED
|
||||||
#define YYSTYPE_DEFINED
|
#define YYSTYPE_DEFINED
|
||||||
typedef union {
|
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_MIN_CLIENT_SUBNET_IPV4 VAR_MIN_CLIENT_SUBNET_IPV6
|
||||||
%token VAR_MAX_ECS_TREE_SIZE_IPV4 VAR_MAX_ECS_TREE_SIZE_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_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_QNAME_MINIMISATION VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND
|
||||||
%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG
|
%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG
|
||||||
%token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION
|
%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_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_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_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_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_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
|
||||||
%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE
|
%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_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
|
||||||
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
|
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
|
||||||
%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE
|
%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 ;
|
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_min_client_subnet_ipv4 | server_min_client_subnet_ipv6 |
|
||||||
server_max_ecs_tree_size_ipv4 | server_max_ecs_tree_size_ipv6 |
|
server_max_ecs_tree_size_ipv4 | server_max_ecs_tree_size_ipv6 |
|
||||||
server_caps_whitelist | server_cache_max_negative_ttl |
|
server_caps_whitelist | server_cache_max_negative_ttl |
|
||||||
|
server_cache_min_negative_ttl |
|
||||||
server_permit_small_holddown | server_qname_minimisation |
|
server_permit_small_holddown | server_qname_minimisation |
|
||||||
server_ip_freebind | server_define_tag | server_local_zone_tag |
|
server_ip_freebind | server_define_tag | server_local_zone_tag |
|
||||||
server_disable_dnssec_lame_check | server_access_control_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_fast_server_permil | server_fast_server_num | server_tls_win_cert |
|
||||||
server_tcp_connection_limit | server_log_servfail | server_deny_any |
|
server_tcp_connection_limit | server_log_servfail | server_deny_any |
|
||||||
server_unknown_server_time_limit | server_log_tag_queryreply |
|
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_stream_wait_size | server_tls_ciphers |
|
||||||
server_tls_ciphersuites | server_tls_session_ticket_keys |
|
server_tls_ciphersuites | server_tls_session_ticket_keys |
|
||||||
server_answer_cookie | server_cookie_secret | server_ip_ratelimit_cookie |
|
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);
|
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
|
server_cache_min_ttl: VAR_CACHE_MIN_TTL STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_cache_min_ttl:%s)\n", $2));
|
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);
|
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
|
server_max_udp_size: VAR_MAX_UDP_SIZE STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_max_udp_size:%s)\n", $2));
|
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 |
|
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
|
||||||
redis_server_host | redis_server_port | redis_timeout |
|
redis_server_host | redis_server_port | redis_timeout |
|
||||||
redis_expire_records | redis_server_path | redis_server_password |
|
redis_expire_records | redis_server_path | redis_server_password |
|
||||||
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
|
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
|
||||||
{
|
{
|
||||||
|
@ -3762,6 +3828,19 @@ cachedb_no_store: VAR_CACHEDB_NO_STORE STRING_ARG
|
||||||
free($2);
|
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
|
redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG
|
||||||
{
|
{
|
||||||
#if defined(USE_CACHEDB) && defined(USE_REDIS)
|
#if defined(USE_CACHEDB) && defined(USE_REDIS)
|
||||||
|
|
|
@ -82,6 +82,8 @@ extern time_t MAX_TTL;
|
||||||
extern time_t MIN_TTL;
|
extern time_t MIN_TTL;
|
||||||
/** Maximum Negative TTL that is allowed */
|
/** Maximum Negative TTL that is allowed */
|
||||||
extern time_t MAX_NEG_TTL;
|
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 */
|
/** If we serve expired entries and prefetch them */
|
||||||
extern int SERVE_EXPIRED;
|
extern int SERVE_EXPIRED;
|
||||||
/** Time to serve records after expiration */
|
/** Time to serve records after expiration */
|
||||||
|
|
|
@ -61,6 +61,8 @@ time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
|
||||||
time_t MIN_TTL = 0;
|
time_t MIN_TTL = 0;
|
||||||
/** MAX Negative TTL, for SOA records in authority section */
|
/** MAX Negative TTL, for SOA records in authority section */
|
||||||
time_t MAX_NEG_TTL = 3600; /* one hour */
|
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 */
|
/** If we serve expired entries and prefetch them */
|
||||||
int SERVE_EXPIRED = 0;
|
int SERVE_EXPIRED = 0;
|
||||||
/** Time to serve records after expiration */
|
/** 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) {
|
if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) {
|
||||||
/* negative response. see if TTL of SOA record larger than the
|
/* negative response. see if TTL of SOA record larger than the
|
||||||
* minimum-ttl in the rdata of the SOA record */
|
* minimum-ttl in the rdata of the SOA record */
|
||||||
if(*rr_ttl > soa_find_minttl(rr))
|
if(*rr_ttl > soa_find_minttl(rr)) *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(!SERVE_ORIGINAL_TTL && (*rr_ttl < MIN_TTL))
|
if(MIN_NEG_TTL <= 0 && *rr_ttl < MIN_TTL) {
|
||||||
*rr_ttl = MIN_TTL;
|
*rr_ttl = MIN_TTL;
|
||||||
if(!SERVE_ORIGINAL_TTL && (*rr_ttl > MAX_TTL))
|
}
|
||||||
*rr_ttl = MAX_TTL;
|
if(*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
|
/* MAX_NEG_TTL overrides the min and max ttl of everything
|
||||||
* else, it is for a more specific record */
|
* else; it is for a more specific record */
|
||||||
if(*rr_ttl > MAX_NEG_TTL)
|
if(*rr_ttl > MAX_NEG_TTL) *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)
|
if(*rr_ttl < data->ttl)
|
||||||
data->ttl = *rr_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 buf[20480];
|
||||||
char* p = buf;
|
char* p = buf;
|
||||||
|
@ -148,7 +148,10 @@ char* errinf_to_str_bogus(struct module_qstate* qstate)
|
||||||
snprintf(p, left, " %s", s->str);
|
snprintf(p, left, " %s", s->str);
|
||||||
left -= strlen(p); p += strlen(p);
|
left -= strlen(p); p += strlen(p);
|
||||||
}
|
}
|
||||||
p = strdup(buf);
|
if(region)
|
||||||
|
p = regional_strdup(region, buf);
|
||||||
|
else
|
||||||
|
p = strdup(buf);
|
||||||
if(!p)
|
if(!p)
|
||||||
log_err("malloc failure in errinf_to_str");
|
log_err("malloc failure in errinf_to_str");
|
||||||
return p;
|
return p;
|
||||||
|
@ -188,7 +191,7 @@ char* errinf_to_str_servfail(struct module_qstate* qstate)
|
||||||
snprintf(p, left, " %s", s->str);
|
snprintf(p, left, " %s", s->str);
|
||||||
left -= strlen(p); p += strlen(p);
|
left -= strlen(p); p += strlen(p);
|
||||||
}
|
}
|
||||||
p = strdup(buf);
|
p = regional_strdup(qstate->region, buf);
|
||||||
if(!p)
|
if(!p)
|
||||||
log_err("malloc failure in errinf_to_str");
|
log_err("malloc failure in errinf_to_str");
|
||||||
return p;
|
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);
|
snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str);
|
||||||
left -= strlen(p); p += strlen(p);
|
left -= strlen(p); p += strlen(p);
|
||||||
}
|
}
|
||||||
p = strdup(buf);
|
p = regional_strdup(qstate->region, buf);
|
||||||
if(!p)
|
if(!p)
|
||||||
log_err("malloc failure in errinf_to_str");
|
log_err("malloc failure in errinf_to_str");
|
||||||
return p;
|
return p;
|
||||||
|
|
|
@ -180,6 +180,7 @@ struct iter_hints;
|
||||||
struct respip_set;
|
struct respip_set;
|
||||||
struct respip_client_info;
|
struct respip_client_info;
|
||||||
struct respip_addr_info;
|
struct respip_addr_info;
|
||||||
|
struct module_stack;
|
||||||
|
|
||||||
/** Maximum number of modules in operation */
|
/** Maximum number of modules in operation */
|
||||||
#define MAX_MODULE 16
|
#define MAX_MODULE 16
|
||||||
|
@ -511,10 +512,10 @@ struct module_env {
|
||||||
/** auth zones */
|
/** auth zones */
|
||||||
struct auth_zones* auth_zones;
|
struct auth_zones* auth_zones;
|
||||||
/** Mapping of forwarding zones to targets.
|
/** Mapping of forwarding zones to targets.
|
||||||
* iterator forwarder information. per-thread, created by worker */
|
* iterator forwarder information. */
|
||||||
struct iter_forwards* fwds;
|
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
|
* The hints -- these aren't stored in the cache because they don't
|
||||||
* expire. The hints are always used to "prime" the cache. Note
|
* expire. The hints are always used to "prime" the cache. Note
|
||||||
* that both root hints and stub zone "hints" are stored in this
|
* that both root hints and stub zone "hints" are stored in this
|
||||||
|
@ -537,6 +538,12 @@ struct module_env {
|
||||||
/** EDNS client string information */
|
/** EDNS client string information */
|
||||||
struct edns_strings* edns_strings;
|
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. */
|
/* Make every mesh state unique, do not aggregate mesh states. */
|
||||||
int unique_mesh;
|
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.
|
* Create error info in string. For validation failures.
|
||||||
* @param qstate: query state.
|
* @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).
|
* @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.
|
* 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.
|
* Create error info in string. For other servfails.
|
||||||
* @param qstate: query state.
|
* @param qstate: query state.
|
||||||
* @return string or NULL on malloc failure (already logged).
|
* @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);
|
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.
|
* Create error info in string. For misc failures that are not servfail.
|
||||||
* @param qstate: query state.
|
* @param qstate: query state.
|
||||||
* @return string or NULL on malloc failure (already logged).
|
* @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);
|
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 */
|
/** max length of an IP address (the address portion) that we allow */
|
||||||
#define MAX_ADDR_STRLEN 128 /* characters */
|
#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 */
|
/** default value for EDNS ADVERTISED size */
|
||||||
uint16_t EDNS_ADVERTISED_SIZE = 4096;
|
uint16_t EDNS_ADVERTISED_SIZE = 4096;
|
||||||
|
|
||||||
|
@ -486,28 +488,38 @@ uint8_t* authextstrtodname(char* str, int* port, char** auth_name)
|
||||||
*port = UNBOUND_DNS_PORT;
|
*port = UNBOUND_DNS_PORT;
|
||||||
*auth_name = NULL;
|
*auth_name = NULL;
|
||||||
if((s=strchr(str, '@'))) {
|
if((s=strchr(str, '@'))) {
|
||||||
|
char buf[MAX_HOST_STRLEN];
|
||||||
|
size_t len = (size_t)(s-str);
|
||||||
char* hash = strchr(s+1, '#');
|
char* hash = strchr(s+1, '#');
|
||||||
if(hash) {
|
if(hash) {
|
||||||
*auth_name = hash+1;
|
*auth_name = hash+1;
|
||||||
} else {
|
} else {
|
||||||
*auth_name = NULL;
|
*auth_name = NULL;
|
||||||
}
|
}
|
||||||
|
if(len >= MAX_HOST_STRLEN) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
(void)strlcpy(buf, str, sizeof(buf));
|
||||||
|
buf[len] = 0;
|
||||||
*port = atoi(s+1);
|
*port = atoi(s+1);
|
||||||
if(*port == 0) {
|
if(*port == 0) {
|
||||||
if(!hash && strcmp(s+1,"0")!=0)
|
if(!hash && strcmp(s+1,"0")!=0)
|
||||||
return 0;
|
return NULL;
|
||||||
if(hash && strncmp(s+1,"0#",2)!=0)
|
if(hash && strncmp(s+1,"0#",2)!=0)
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
*s = 0;
|
dname = sldns_str2wire_dname(buf, &dname_len);
|
||||||
dname = sldns_str2wire_dname(str, &dname_len);
|
|
||||||
*s = '@';
|
|
||||||
} else if((s=strchr(str, '#'))) {
|
} 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;
|
*port = UNBOUND_DNS_OVER_TLS_PORT;
|
||||||
*auth_name = s+1;
|
*auth_name = s+1;
|
||||||
*s = 0;
|
dname = sldns_str2wire_dname(buf, &dname_len);
|
||||||
dname = sldns_str2wire_dname(str, &dname_len);
|
|
||||||
*s = '#';
|
|
||||||
} else {
|
} else {
|
||||||
dname = sldns_str2wire_dname(str, &dname_len);
|
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 {
|
} else {
|
||||||
if(print_errno) {
|
if(print_errno) {
|
||||||
if(errno == 0)
|
if(errno == 0)
|
||||||
log_err("str: syscall error with errno %s",
|
log_err("%s: syscall error with errno %s",
|
||||||
strerror(errno));
|
str, strerror(errno));
|
||||||
else log_err("str: %s", strerror(errno));
|
else log_err("%s: %s", str, strerror(errno));
|
||||||
} else {
|
} 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
|
* sending src (client)/dst (local service) addresses over DNSTAP from udp callback
|
||||||
*/
|
*/
|
||||||
if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) {
|
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);
|
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
|
#endif
|
||||||
} else {
|
} 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
|
* 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) {
|
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);
|
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 ));
|
( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer ));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -181,6 +181,8 @@ struct comm_point {
|
||||||
/** if the event is added or not */
|
/** if the event is added or not */
|
||||||
int event_added;
|
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;
|
struct unbound_socket* socket;
|
||||||
|
|
||||||
/** file descriptor for communication point */
|
/** 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) && \
|
# if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
|
||||||
__BYTE_ORDER == __LITTLE_ENDIAN) || \
|
__BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||||
(defined(i386) || defined(__i386__) || defined(__i486__) || \
|
(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_LITTLE_ENDIAN 1
|
||||||
# define HASH_BIG_ENDIAN 0
|
# define HASH_BIG_ENDIAN 0
|
||||||
# elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
|
# 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);
|
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
|
void
|
||||||
lruhash_traverse(struct lruhash* h, int wr,
|
lruhash_traverse(struct lruhash* h, int wr,
|
||||||
void (*func)(struct lruhash_entry*, void*), void* arg)
|
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);
|
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 ************************/
|
/************************* getdns functions ************************/
|
||||||
/*** these are used by getdns only and not by unbound. ***/
|
/*** 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;
|
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 slabhash_get_mem(struct slabhash* sl)
|
||||||
{
|
{
|
||||||
size_t i, total = sizeof(*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);
|
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.
|
* Retrieve slab hash current memory use.
|
||||||
* @param table: hash table.
|
* @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)
|
if(rcode == LDNS_RCODE_NOERROR && qinf->qtype == LDNS_RR_TYPE_ANY)
|
||||||
return VAL_CLASS_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
|
/* Note that DNAMEs will be ignored here, unless qtype=DNAME. Unless
|
||||||
* qtype=CNAME, this will yield a CNAME response. */
|
* qtype=CNAME, this will yield a CNAME response. */
|
||||||
for(i=skip; i<rep->an_numrrsets; i++) {
|
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) {
|
rep->rrsets[i]->rk.dname) == 0) {
|
||||||
val_find_rrset_signer(rep->rrsets[i],
|
val_find_rrset_signer(rep->rrsets[i],
|
||||||
signer_name, signer_len);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ fill_nsec3_iter(struct val_env* ve, char* s, int c)
|
||||||
s = e;
|
s = e;
|
||||||
if(i>0 && ve->nsec3_keysize[i-1] >= ve->nsec3_keysize[i]) {
|
if(i>0 && ve->nsec3_keysize[i-1] >= ve->nsec3_keysize[i]) {
|
||||||
log_err("nsec3 key iterations not ascending: %d %d",
|
log_err("nsec3 key iterations not ascending: %d %d",
|
||||||
(int)ve->nsec3_keysize[i-1],
|
(int)ve->nsec3_keysize[i-1],
|
||||||
(int)ve->nsec3_keysize[i]);
|
(int)ve->nsec3_keysize[i]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -621,7 +621,6 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
* @param vq: validator query state.
|
* @param vq: validator query state.
|
||||||
* @param env: module env for verify.
|
* @param env: module env for verify.
|
||||||
* @param ve: validator env for verify.
|
* @param ve: validator env for verify.
|
||||||
* @param qchase: query that was made.
|
|
||||||
* @param chase_reply: answer to validate.
|
* @param chase_reply: answer to validate.
|
||||||
* @param key_entry: the key entry, which is trusted, and which matches
|
* @param key_entry: the key entry, which is trusted, and which matches
|
||||||
* the signer of the answer. The key entry isgood().
|
* 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
|
static int
|
||||||
validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
|
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,
|
struct reply_info* chase_reply, struct key_entry_key* key_entry,
|
||||||
int* suspend)
|
int* suspend)
|
||||||
{
|
{
|
||||||
|
@ -640,7 +639,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
size_t i, slen;
|
size_t i, slen;
|
||||||
struct ub_packed_rrset_key* s;
|
struct ub_packed_rrset_key* s;
|
||||||
enum sec_status sec;
|
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;
|
char* reason = NULL;
|
||||||
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
|
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
|
||||||
*suspend = 0;
|
*suspend = 0;
|
||||||
|
@ -658,9 +657,13 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
/* Skip the CNAME following a (validated) DNAME.
|
/* Skip the CNAME following a (validated) DNAME.
|
||||||
* Because of the normalization routines in the iterator,
|
* Because of the normalization routines in the iterator,
|
||||||
* there will always be an unsigned CNAME following a DNAME
|
* there will always be an unsigned CNAME following a DNAME
|
||||||
* (unless qtype=DNAME). */
|
* (unless qtype=DNAME in the answer part). */
|
||||||
if(dname_seen && ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) {
|
if(i>0 && ntohs(chase_reply->rrsets[i-1]->rk.type) ==
|
||||||
dname_seen = 0;
|
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 */
|
/* CNAME was synthesized by our own iterator */
|
||||||
/* since the DNAME verified, mark the CNAME as secure */
|
/* since the DNAME verified, mark the CNAME as secure */
|
||||||
((struct packed_rrset_data*)s->entry.data)->security =
|
((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;
|
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;
|
num_verifies += verified;
|
||||||
if(num_verifies > MAX_VALIDATE_AT_ONCE &&
|
if(num_verifies > MAX_VALIDATE_AT_ONCE &&
|
||||||
i+1 < (env->cfg->val_clean_additional?
|
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;
|
/* check signatures in the message;
|
||||||
* answer and authority must be valid, additional is only checked. */
|
* 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)) {
|
vq->chase_reply, vq->key_entry, &suspend)) {
|
||||||
if(suspend) {
|
if(suspend) {
|
||||||
if(!validate_suspend_setup_timer(qstate, vq,
|
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",
|
log_query_info(NO_VERBOSE, "validation failure",
|
||||||
&qstate->qinfo);
|
&qstate->qinfo);
|
||||||
else {
|
else {
|
||||||
char* err_str = errinf_to_str_bogus(qstate);
|
char* err_str = errinf_to_str_bogus(qstate,
|
||||||
|
qstate->region);
|
||||||
if(err_str) {
|
if(err_str) {
|
||||||
size_t err_str_len = strlen(err_str);
|
|
||||||
log_info("%s", err_str);
|
log_info("%s", err_str);
|
||||||
/* allocate space and store the error
|
vq->orig_msg->rep->reason_bogus_str = err_str;
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
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
|
* Copyright (c) 1996 Michael Shalayeff
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
#include "efipxe.h"
|
#include "efipxe.h"
|
||||||
#include "softraid_arm64.h"
|
#include "softraid_arm64.h"
|
||||||
|
|
||||||
const char version[] = "1.18";
|
const char version[] = "1.19";
|
||||||
int debug = 0;
|
int debug = 0;
|
||||||
|
|
||||||
struct fs_ops file_system[] = {
|
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>
|
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
|
||||||
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "efidev.h"
|
#include "efidev.h"
|
||||||
#include "efiboot.h"
|
#include "efiboot.h"
|
||||||
|
#include "efidt.h"
|
||||||
#include "fdt.h"
|
#include "fdt.h"
|
||||||
|
|
||||||
EFI_SYSTEM_TABLE *ST;
|
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 fdt_guid = FDT_TABLE_GUID;
|
||||||
static EFI_GUID smbios_guid = SMBIOS_TABLE_GUID;
|
static EFI_GUID smbios_guid = SMBIOS_TABLE_GUID;
|
||||||
static EFI_GUID smbios3_guid = SMBIOS3_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))
|
#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;
|
return fdt_override ? fdt_override : fdt_sys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define EXTRA_DT_SPACE (32 * 1024)
|
||||||
|
|
||||||
int
|
int
|
||||||
fdt_load_override(char *file)
|
fdt_load_override(char *file)
|
||||||
{
|
{
|
||||||
|
EFI_DT_FIXUP_PROTOCOL *dt_fixup;
|
||||||
EFI_PHYSICAL_ADDRESS addr;
|
EFI_PHYSICAL_ADDRESS addr;
|
||||||
char path[MAXPATHLEN];
|
char path[MAXPATHLEN];
|
||||||
|
EFI_STATUS status;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
size_t dt_size;
|
||||||
|
UINTN sz;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (file == NULL && fdt_override) {
|
if (file == NULL && fdt_override) {
|
||||||
|
@ -1157,7 +1165,8 @@ fdt_load_override(char *file)
|
||||||
printf("cannot open %s\n", path);
|
printf("cannot open %s\n", path);
|
||||||
return 0;
|
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) {
|
PAGE_SIZE, EfiLoaderData, &addr) != EFI_SUCCESS) {
|
||||||
printf("cannot allocate memory for %s\n", path);
|
printf("cannot allocate memory for %s\n", path);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1167,9 +1176,18 @@ fdt_load_override(char *file)
|
||||||
return 0;
|
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)) {
|
if (!fdt_init((void *)addr)) {
|
||||||
printf("invalid device tree\n");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1180,7 +1198,7 @@ fdt_load_override(char *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fdt_override = (void *)addr;
|
fdt_override = (void *)addr;
|
||||||
fdt_override_size = sb.st_size;
|
fdt_override_size = dt_size;
|
||||||
return 0;
|
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>
|
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
|
||||||
|
@ -68,7 +68,7 @@ void ufshci_dmamem_free(struct ufshci_softc *,
|
||||||
struct ufshci_dmamem *);
|
struct ufshci_dmamem *);
|
||||||
int ufshci_alloc(struct ufshci_softc *);
|
int ufshci_alloc(struct ufshci_softc *);
|
||||||
int ufshci_init(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 *);
|
int ufshci_doorbell_read(struct ufshci_softc *);
|
||||||
void ufshci_doorbell_write(struct ufshci_softc *, int);
|
void ufshci_doorbell_write(struct ufshci_softc *, int);
|
||||||
int ufshci_doorbell_poll(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 *,
|
int ufshci_utr_cmd_sync(struct ufshci_softc *,
|
||||||
struct ufshci_ccb *, struct scsi_xfer *,
|
struct ufshci_ccb *, struct scsi_xfer *,
|
||||||
uint32_t, uint16_t);
|
uint32_t, uint16_t);
|
||||||
int ufshci_xfer_complete(struct ufshci_softc *);
|
void ufshci_xfer_complete(struct ufshci_softc *);
|
||||||
|
|
||||||
/* SCSI */
|
/* SCSI */
|
||||||
int ufshci_ccb_alloc(struct ufshci_softc *, int);
|
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);
|
DPRINTF(3, "%s: status=0x%08x\n", __func__, status);
|
||||||
|
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
return 0;
|
return handled;
|
||||||
|
|
||||||
if (status & UFSHCI_REG_IS_UCCS) {
|
if (status & UFSHCI_REG_IS_UCCS) {
|
||||||
DPRINTF(3, "%s: UCCS interrupt\n", __func__);
|
DPRINTF(3, "%s: UCCS interrupt\n", __func__);
|
||||||
|
@ -149,11 +149,13 @@ ufshci_intr(void *arg)
|
||||||
hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
|
hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
|
||||||
printf("%s: Auto-Hibernate enter error UPMCRS=0x%x\n",
|
printf("%s: Auto-Hibernate enter error UPMCRS=0x%x\n",
|
||||||
__func__, UFSHCI_REG_HCS_UPMCRS(hcs));
|
__func__, UFSHCI_REG_HCS_UPMCRS(hcs));
|
||||||
|
handled = 1;
|
||||||
}
|
}
|
||||||
if (status & UFSHCI_REG_IS_UHXS) {
|
if (status & UFSHCI_REG_IS_UHXS) {
|
||||||
hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
|
hcs = UFSHCI_READ_4(sc, UFSHCI_REG_HCS);
|
||||||
printf("%s: Auto-Hibernate exit error UPMCRS=0x%x\n",
|
printf("%s: Auto-Hibernate exit error UPMCRS=0x%x\n",
|
||||||
__func__, UFSHCI_REG_HCS_UPMCRS(hcs));
|
__func__, UFSHCI_REG_HCS_UPMCRS(hcs));
|
||||||
|
handled = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handled == 0) {
|
if (handled == 0) {
|
||||||
|
@ -164,7 +166,7 @@ ufshci_intr(void *arg)
|
||||||
/* ACK interrupt */
|
/* ACK interrupt */
|
||||||
UFSHCI_WRITE_4(sc, UFSHCI_REG_IS, status);
|
UFSHCI_WRITE_4(sc, UFSHCI_REG_IS, status);
|
||||||
|
|
||||||
return 1;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -177,7 +179,8 @@ ufshci_attach(struct ufshci_softc *sc)
|
||||||
SIMPLEQ_INIT(&sc->sc_ccb_list);
|
SIMPLEQ_INIT(&sc->sc_ccb_list);
|
||||||
scsi_iopool_init(&sc->sc_iopool, sc, ufshci_ccb_get, ufshci_ccb_put);
|
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);
|
sc->sc_ver = UFSHCI_READ_4(sc, UFSHCI_REG_VER);
|
||||||
printf(", UFSHCI %d.%d%d\n",
|
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 */
|
sc->sc_flags |= UFSHCI_FLAGS_AGGR_INTR; /* Enable intr. aggregation */
|
||||||
#endif
|
#endif
|
||||||
/* Allocate the DMA buffers and initialize the controller. */
|
/* Allocate the DMA buffers and initialize the controller. */
|
||||||
ufshci_alloc(sc);
|
if (ufshci_alloc(sc))
|
||||||
ufshci_init(sc);
|
return 1;
|
||||||
|
if (ufshci_init(sc))
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (ufshci_ccb_alloc(sc, sc->sc_nutrs) != 0) {
|
if (ufshci_ccb_alloc(sc, sc->sc_nutrs) != 0) {
|
||||||
printf("%s: %s: Can't allocate CCBs\n",
|
printf("%s: %s: Can't allocate CCBs\n",
|
||||||
|
@ -294,7 +299,7 @@ ufshci_reset(struct ufshci_softc *sc)
|
||||||
if (i == retry) {
|
if (i == retry) {
|
||||||
printf("%s: Enabling Host Controller failed!\n",
|
printf("%s: Enabling Host Controller failed!\n",
|
||||||
sc->sc_dev.dv_xname);
|
sc->sc_dev.dv_xname);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(2, "\n%s: Host Controller enabled (i=%d)\n", __func__, i);
|
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) {
|
if (i == retry) {
|
||||||
printf("%s: %s: timeout\n", sc->sc_dev.dv_xname, __func__);
|
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);
|
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) {
|
if (sc->sc_dmamem_utmrd == NULL) {
|
||||||
printf("%s: Can't allocate DMA memory for UTMRD\n",
|
printf("%s: Can't allocate DMA memory for UTMRD\n",
|
||||||
sc->sc_dev.dv_xname);
|
sc->sc_dev.dv_xname);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7.1.1 Host Controller Initialization: 15) */
|
/* 7.1.1 Host Controller Initialization: 15) */
|
||||||
|
@ -403,7 +408,7 @@ ufshci_alloc(struct ufshci_softc *sc)
|
||||||
if (sc->sc_dmamem_utrd == NULL) {
|
if (sc->sc_dmamem_utrd == NULL) {
|
||||||
printf("%s: Can't allocate DMA memory for UTRD\n",
|
printf("%s: Can't allocate DMA memory for UTRD\n",
|
||||||
sc->sc_dev.dv_xname);
|
sc->sc_dev.dv_xname);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate UCDs. */
|
/* Allocate UCDs. */
|
||||||
|
@ -412,7 +417,7 @@ ufshci_alloc(struct ufshci_softc *sc)
|
||||||
if (sc->sc_dmamem_ucd == NULL) {
|
if (sc->sc_dmamem_ucd == NULL) {
|
||||||
printf("%s: Can't allocate DMA memory for UCD\n",
|
printf("%s: Can't allocate DMA memory for UCD\n",
|
||||||
sc->sc_dev.dv_xname);
|
sc->sc_dev.dv_xname);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -442,8 +447,8 @@ ufshci_init(struct ufshci_softc *sc)
|
||||||
/* 7.1.1 Host Controller Initialization: 6) */
|
/* 7.1.1 Host Controller Initialization: 6) */
|
||||||
UFSHCI_WRITE_4(sc, UFSHCI_REG_UICCMD,
|
UFSHCI_WRITE_4(sc, UFSHCI_REG_UICCMD,
|
||||||
UFSHCI_REG_UICCMD_CMDOP_DME_LINKSTARTUP);
|
UFSHCI_REG_UICCMD_CMDOP_DME_LINKSTARTUP);
|
||||||
if (ufshci_is_poll(sc, UFSHCI_REG_IS_UCCS) != 0)
|
if (ufshci_is_poll(sc, UFSHCI_REG_IS_UCCS))
|
||||||
return -1;
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 7.1.1 Host Controller Initialization: 7), 8), 9)
|
* 7.1.1 Host Controller Initialization: 7), 8), 9)
|
||||||
|
@ -503,7 +508,7 @@ ufshci_init(struct ufshci_softc *sc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
ufshci_disable(struct ufshci_softc *sc)
|
ufshci_disable(struct ufshci_softc *sc)
|
||||||
{
|
{
|
||||||
/* Stop run queues. */
|
/* Stop run queues. */
|
||||||
|
@ -512,8 +517,6 @@ ufshci_disable(struct ufshci_softc *sc)
|
||||||
|
|
||||||
/* Disable interrupts. */
|
/* Disable interrupts. */
|
||||||
UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, 0);
|
UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, 0);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -553,7 +556,7 @@ ufshci_doorbell_poll(struct ufshci_softc *sc, int slot, uint32_t timeout_ms)
|
||||||
}
|
}
|
||||||
if (timeout_us == 0) {
|
if (timeout_us == 0) {
|
||||||
printf("%s: %s: timeout\n", sc->sc_dev.dv_xname, __func__);
|
printf("%s: %s: timeout\n", sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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) {
|
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||||
printf("%s: %s: UTRLRSR not set\n",
|
printf("%s: %s: UTRLRSR not set\n",
|
||||||
sc->sc_dev.dv_xname, __func__);
|
sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
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) {
|
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||||
printf("%s: %s: UTRLRSR not set\n",
|
printf("%s: %s: UTRLRSR not set\n",
|
||||||
sc->sc_dev.dv_xname, __func__);
|
sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
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) {
|
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||||
printf("%s: %s: UTRLRSR not set\n",
|
printf("%s: %s: UTRLRSR not set\n",
|
||||||
sc->sc_dev.dv_xname, __func__);
|
sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
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;
|
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||||
ufshci_doorbell_write(sc, slot);
|
ufshci_doorbell_write(sc, slot);
|
||||||
|
|
||||||
return slot;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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) {
|
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||||
printf("%s: %s: UTRLRSR not set\n",
|
printf("%s: %s: UTRLRSR not set\n",
|
||||||
sc->sc_dev.dv_xname, __func__);
|
sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
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;
|
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||||
ufshci_doorbell_write(sc, slot);
|
ufshci_doorbell_write(sc, slot);
|
||||||
|
|
||||||
return slot;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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) {
|
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||||
printf("%s: %s: UTRLRSR not set\n",
|
printf("%s: %s: UTRLRSR not set\n",
|
||||||
sc->sc_dev.dv_xname, __func__);
|
sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
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;
|
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||||
ufshci_doorbell_write(sc, slot);
|
ufshci_doorbell_write(sc, slot);
|
||||||
|
|
||||||
return slot;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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) {
|
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||||
printf("%s: %s: UTRLRSR not set\n",
|
printf("%s: %s: UTRLRSR not set\n",
|
||||||
sc->sc_dev.dv_xname, __func__);
|
sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
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;
|
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||||
ufshci_doorbell_write(sc, slot);
|
ufshci_doorbell_write(sc, slot);
|
||||||
|
|
||||||
return slot;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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) {
|
if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
|
||||||
printf("%s: %s: UTRLRSR not set\n",
|
printf("%s: %s: UTRLRSR not set\n",
|
||||||
sc->sc_dev.dv_xname, __func__);
|
sc->sc_dev.dv_xname, __func__);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
|
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;
|
ccb->ccb_status = CCB_STATUS_INPROGRESS;
|
||||||
ufshci_doorbell_write(sc, slot);
|
ufshci_doorbell_write(sc, slot);
|
||||||
|
|
||||||
return slot;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
ufshci_xfer_complete(struct ufshci_softc *sc)
|
ufshci_xfer_complete(struct ufshci_softc *sc)
|
||||||
{
|
{
|
||||||
struct ufshci_ccb *ccb;
|
struct ufshci_ccb *ccb;
|
||||||
|
@ -1374,8 +1377,6 @@ ufshci_xfer_complete(struct ufshci_softc *sc)
|
||||||
if (ccb->ccb_status == CCB_STATUS_READY2FREE)
|
if (ccb->ccb_status == CCB_STATUS_READY2FREE)
|
||||||
ccb->ccb_done(sc, ccb);
|
ccb->ccb_done(sc, ccb);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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,
|
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
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);
|
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||||
goto error1;
|
goto error1;
|
||||||
}
|
}
|
||||||
|
@ -1602,7 +1603,7 @@ ufshci_scsi_inquiry(struct scsi_xfer *xs)
|
||||||
|
|
||||||
/* Response length should be UPIU_SCSI_RSP_INQUIRY_SIZE. */
|
/* Response length should be UPIU_SCSI_RSP_INQUIRY_SIZE. */
|
||||||
error = ufshci_utr_cmd_inquiry(sc, ccb, xs);
|
error = ufshci_utr_cmd_inquiry(sc, ccb, xs);
|
||||||
if (error == -1)
|
if (error)
|
||||||
goto error2;
|
goto error2;
|
||||||
|
|
||||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
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,
|
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
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);
|
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||||
goto error1;
|
goto error1;
|
||||||
}
|
}
|
||||||
|
@ -1657,7 +1658,7 @@ ufshci_scsi_capacity16(struct scsi_xfer *xs)
|
||||||
|
|
||||||
/* Response length should be UPIU_SCSI_RSP_CAPACITY16_SIZE. */
|
/* Response length should be UPIU_SCSI_RSP_CAPACITY16_SIZE. */
|
||||||
error = ufshci_utr_cmd_capacity16(sc, ccb, xs);
|
error = ufshci_utr_cmd_capacity16(sc, ccb, xs);
|
||||||
if (error == -1)
|
if (error)
|
||||||
goto error2;
|
goto error2;
|
||||||
|
|
||||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
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,
|
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
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);
|
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||||
goto error1;
|
goto error1;
|
||||||
}
|
}
|
||||||
|
@ -1712,7 +1713,7 @@ ufshci_scsi_capacity(struct scsi_xfer *xs)
|
||||||
|
|
||||||
/* Response length should be UPIU_SCSI_RSP_CAPACITY_SIZE */
|
/* Response length should be UPIU_SCSI_RSP_CAPACITY_SIZE */
|
||||||
error = ufshci_utr_cmd_capacity(sc, ccb, xs);
|
error = ufshci_utr_cmd_capacity(sc, ccb, xs);
|
||||||
if (error == -1)
|
if (error)
|
||||||
goto error2;
|
goto error2;
|
||||||
|
|
||||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
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,
|
error = ufshci_utr_cmd_sync(sc, ccb, xs, (uint32_t)lba,
|
||||||
(uint16_t)blocks);
|
(uint16_t)blocks);
|
||||||
if (error == -1)
|
if (error)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
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,
|
error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
|
||||||
ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
|
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);
|
printf("%s: bus_dmamap_load error=%d\n", __func__, error);
|
||||||
goto error1;
|
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);
|
error = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_IN);
|
||||||
else
|
else
|
||||||
error = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_OUT);
|
error = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_OUT);
|
||||||
if (error == -1)
|
if (error)
|
||||||
goto error2;
|
goto error2;
|
||||||
|
|
||||||
if (ISSET(xs->flags, SCSI_POLL)) {
|
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
|
* Copyright (c) 2016 Mark Kettenis
|
||||||
*
|
*
|
||||||
|
@ -56,6 +56,11 @@ regulator_register(struct regulator_device *rd)
|
||||||
rd->rd_ramp_delay =
|
rd->rd_ramp_delay =
|
||||||
OF_getpropint(rd->rd_node, "regulator-ramp-delay", 0);
|
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) {
|
if (rd->rd_get_voltage && rd->rd_set_voltage) {
|
||||||
uint32_t voltage = rd->rd_get_voltage(rd->rd_cookie);
|
uint32_t voltage = rd->rd_get_voltage(rd->rd_cookie);
|
||||||
if (voltage < rd->rd_volt_min)
|
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))
|
if (rd && (voltage < rd->rd_volt_min || voltage > rd->rd_volt_max))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
/* XXX Coupled regulators are unsupported for now. */
|
||||||
|
if (rd && rd->rd_coupled)
|
||||||
|
return ENOTSUP;
|
||||||
|
|
||||||
if (rd && rd->rd_set_voltage) {
|
if (rd && rd->rd_set_voltage) {
|
||||||
regulator_do_notify(rd->rd_phandle, 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
|
* Copyright (c) 2016 Mark Kettenis
|
||||||
*
|
*
|
||||||
|
@ -31,6 +31,9 @@ struct regulator_device {
|
||||||
uint32_t rd_amp_min, rd_amp_max;
|
uint32_t rd_amp_min, rd_amp_max;
|
||||||
uint32_t rd_ramp_delay;
|
uint32_t rd_ramp_delay;
|
||||||
|
|
||||||
|
uint32_t rd_coupled;
|
||||||
|
uint32_t rd_max_spread;
|
||||||
|
|
||||||
LIST_ENTRY(regulator_device) rd_list;
|
LIST_ENTRY(regulator_device) rd_list;
|
||||||
uint32_t rd_phandle;
|
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;
|
void __iomem *addr;
|
||||||
u32 val;
|
u32 val;
|
||||||
int i;
|
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
|
/* The caller expects to ver, rel and step to be initialized
|
||||||
* here, and there's no good way to check when there was a
|
* 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;
|
*rel = 0;
|
||||||
*step = 0;
|
*step = 0;
|
||||||
|
|
||||||
STUB();
|
#ifdef __linux__
|
||||||
return &no_display;
|
|
||||||
#ifdef notyet
|
|
||||||
addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32));
|
addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32));
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n");
|
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);
|
val = ioread32(addr);
|
||||||
pci_iounmap(pdev, 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) {
|
if (val == 0) {
|
||||||
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
|
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",
|
drm_err(&i915->drm, "Unrecognized display IP version %d.%02d; disabling display.\n",
|
||||||
*ver, *rel);
|
*ver, *rel);
|
||||||
return &no_display;
|
return &no_display;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct intel_display_device_info *
|
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);
|
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) {
|
switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) {
|
||||||
case GEN8_STOLEN_RESERVED_1M:
|
case GEN8_STOLEN_RESERVED_1M:
|
||||||
*size = 1024 * 1024;
|
*size = 1024 * 1024;
|
||||||
|
|
|
@ -470,6 +470,9 @@
|
||||||
#define XEHP_PSS_MODE2 MCR_REG(0x703c)
|
#define XEHP_PSS_MODE2 MCR_REG(0x703c)
|
||||||
#define SCOREBOARD_STALL_FLUSH_CONTROL REG_BIT(5)
|
#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 GEN7_SC_INSTDONE _MMIO(0x7100)
|
||||||
#define GEN12_SC_INSTDONE_EXTRA _MMIO(0x7104)
|
#define GEN12_SC_INSTDONE_EXTRA _MMIO(0x7104)
|
||||||
#define GEN12_SC_INSTDONE_EXTRA2 _MMIO(0x7108)
|
#define GEN12_SC_INSTDONE_EXTRA2 _MMIO(0x7108)
|
||||||
|
@ -538,6 +541,9 @@
|
||||||
#define XEHP_SQCM MCR_REG(0x8724)
|
#define XEHP_SQCM MCR_REG(0x8724)
|
||||||
#define EN_32B_ACCESS REG_BIT(30)
|
#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 HSW_IDICR _MMIO(0x9008)
|
||||||
#define IDIHASHMSK(x) (((x) & 0x3f) << 16)
|
#define IDIHASHMSK(x) (((x) & 0x3f) << 16)
|
||||||
|
|
||||||
|
@ -1209,6 +1215,7 @@
|
||||||
#define GEN12_DISABLE_EARLY_READ REG_BIT(14)
|
#define GEN12_DISABLE_EARLY_READ REG_BIT(14)
|
||||||
#define GEN12_ENABLE_LARGE_GRF_MODE REG_BIT(12)
|
#define GEN12_ENABLE_LARGE_GRF_MODE REG_BIT(12)
|
||||||
#define GEN12_PUSH_CONST_DEREF_HOLD_DIS REG_BIT(8)
|
#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 GEN12_DISABLE_DOP_GATING REG_BIT(0)
|
||||||
|
|
||||||
#define RT_CTRL MCR_REG(0xe530)
|
#define RT_CTRL MCR_REG(0xe530)
|
||||||
|
@ -1221,6 +1228,8 @@
|
||||||
|
|
||||||
#define XEHP_HDC_CHICKEN0 MCR_REG(0xe5f0)
|
#define XEHP_HDC_CHICKEN0 MCR_REG(0xe5f0)
|
||||||
#define LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK REG_GENMASK(13, 11)
|
#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 ICL_HDC_MODE MCR_REG(0xe5f4)
|
||||||
|
|
||||||
#define EU_PERF_CNTL2 PERF_REG(0xe658)
|
#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_18019271663:dg2 */
|
||||||
wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE);
|
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,
|
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_18019271663 */
|
||||||
wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE);
|
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,
|
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);
|
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)) {
|
if (IS_DG2_G11(i915) || IS_DG2_G10(i915)) {
|
||||||
/* Wa_22014600077:dg2 */
|
/* Wa_22014600077:dg2 */
|
||||||
wa_mcr_add(wal, GEN10_CACHE_MODE_SS, 0,
|
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) ||
|
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_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_14017856879 */
|
||||||
wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN3, MTL_DISABLE_FIX_FOR_EOT_FLUSH);
|
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) ||
|
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))
|
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 mmio_bar, mmio_size, mmio_type;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
dev_priv->pa = pa;
|
||||||
dev_priv->pc = pa->pa_pc;
|
dev_priv->pc = pa->pa_pc;
|
||||||
dev_priv->tag = pa->pa_tag;
|
dev_priv->tag = pa->pa_tag;
|
||||||
dev_priv->iot = pa->pa_iot;
|
dev_priv->iot = pa->pa_iot;
|
||||||
|
|
|
@ -239,6 +239,7 @@ struct inteldrm_softc {
|
||||||
struct i915_dsm dsm;
|
struct i915_dsm dsm;
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
|
struct pci_attach_args *pa;
|
||||||
pci_chipset_tag_t pc;
|
pci_chipset_tag_t pc;
|
||||||
pcitag_t tag;
|
pcitag_t tag;
|
||||||
struct extent *memex;
|
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)
|
static void ip_ver_read(struct drm_i915_private *i915, u32 offset, struct intel_ip_version *ip)
|
||||||
{
|
{
|
||||||
STUB();
|
#ifdef __linux__
|
||||||
#ifdef notyet
|
|
||||||
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
|
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
|
||||||
void __iomem *addr;
|
void __iomem *addr;
|
||||||
|
#endif
|
||||||
u32 val;
|
u32 val;
|
||||||
u8 expected_ver = ip->ver;
|
u8 expected_ver = ip->ver;
|
||||||
u8 expected_rel = ip->rel;
|
u8 expected_rel = ip->rel;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
addr = pci_iomap_range(pdev, 0, offset, sizeof(u32));
|
addr = pci_iomap_range(pdev, 0, offset, sizeof(u32));
|
||||||
if (drm_WARN_ON(&i915->drm, !addr))
|
if (drm_WARN_ON(&i915->drm, !addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
val = ioread32(addr);
|
val = ioread32(addr);
|
||||||
pci_iounmap(pdev, 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->ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val);
|
||||||
ip->rel = REG_FIELD_GET(GMD_ID_RELEASE_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,
|
drm_dbg(&i915->drm,
|
||||||
"Hardware reports GMD IP version %u.%u (REG[0x%x] = 0x%08x) but minimum expected is %u.%u\n",
|
"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);
|
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.
|
* 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.
|
* This function mixes entropy and timing into the entropy input ring.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
enqueue_randomness(u_int val)
|
add_event_data(u_int val)
|
||||||
{
|
{
|
||||||
struct rand_event *rep;
|
struct rand_event *rep;
|
||||||
int e;
|
int e;
|
||||||
|
@ -182,6 +182,12 @@ enqueue_randomness(u_int val)
|
||||||
rep = &rnd_event_space[e];
|
rep = &rnd_event_space[e];
|
||||||
rep->re_time += cpu_rnd_messybits();
|
rep->re_time += cpu_rnd_messybits();
|
||||||
rep->re_val += val;
|
rep->re_val += val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
enqueue_randomness(u_int val)
|
||||||
|
{
|
||||||
|
add_event_data(val);
|
||||||
|
|
||||||
if (rnd_cold) {
|
if (rnd_cold) {
|
||||||
dequeue_randomness(NULL);
|
dequeue_randomness(NULL);
|
||||||
|
@ -248,9 +254,6 @@ dequeue_randomness(void *v)
|
||||||
u_int32_t buf[2];
|
u_int32_t buf[2];
|
||||||
u_int startp, startc, i;
|
u_int startp, startc, i;
|
||||||
|
|
||||||
if (!rnd_cold)
|
|
||||||
timeout_del(&rnd_timeout);
|
|
||||||
|
|
||||||
/* Some very new damage */
|
/* Some very new damage */
|
||||||
startp = rnd_event_prod - QEVCONSUME;
|
startp = rnd_event_prod - QEVCONSUME;
|
||||||
for (i = 0; i < QEVCONSUME; i++) {
|
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.
|
* Modify pool so next hash will produce different results.
|
||||||
* During boot-time enqueue/dequeue stage, avoid recursion.
|
*/
|
||||||
*/
|
add_event_data(extract_pool[0]);
|
||||||
if (!rnd_cold)
|
|
||||||
enqueue_randomness(extract_pool[0]);
|
|
||||||
dequeue_randomness(NULL);
|
dequeue_randomness(NULL);
|
||||||
|
|
||||||
/* Wipe data from memory */
|
/* 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 $ */
|
/* $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;
|
break;
|
||||||
case AF_KEY:
|
case AF_KEY:
|
||||||
|
case AF_ROUTE:
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
so->so_snd.sb_flags |= SB_MTXLOCK;
|
so->so_snd.sb_flags |= SB_MTXLOCK;
|
||||||
so->so_rcv.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 $ */
|
/* $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
|
* If we are in a FLUSH state, check if the buffer is
|
||||||
* empty so that we can clear the flag.
|
* empty so that we can clear the flag.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mtx_enter(&so->so_rcv.sb_mtx);
|
||||||
if (((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0) &&
|
if (((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0) &&
|
||||||
((sbspace(rop->rop_socket, &rop->rop_socket->so_rcv) ==
|
((sbspace(so, &so->so_rcv) == so->so_rcv.sb_hiwat)))
|
||||||
rop->rop_socket->so_rcv.sb_hiwat)))
|
|
||||||
rop->rop_flags &= ~ROUTECB_FLAG_FLUSH;
|
rop->rop_flags &= ~ROUTECB_FLAG_FLUSH;
|
||||||
|
mtx_leave(&so->so_rcv.sb_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -478,8 +480,14 @@ rtm_senddesync(struct socket *so)
|
||||||
*/
|
*/
|
||||||
desync_mbuf = rtm_msg1(RTM_DESYNC, NULL);
|
desync_mbuf = rtm_msg1(RTM_DESYNC, NULL);
|
||||||
if (desync_mbuf != NULL) {
|
if (desync_mbuf != NULL) {
|
||||||
if (sbappendaddr(so, &so->so_rcv, &route_src,
|
int ret;
|
||||||
desync_mbuf, NULL) != 0) {
|
|
||||||
|
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;
|
rop->rop_flags &= ~ROUTECB_FLAG_DESYNC;
|
||||||
sorwakeup(rop->rop_socket);
|
sorwakeup(rop->rop_socket);
|
||||||
return;
|
return;
|
||||||
|
@ -586,6 +594,7 @@ rtm_sendup(struct socket *so, struct mbuf *m0)
|
||||||
{
|
{
|
||||||
struct rtpcb *rop = sotortpcb(so);
|
struct rtpcb *rop = sotortpcb(so);
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
|
int send_desync = 0;
|
||||||
|
|
||||||
soassertlocked(so);
|
soassertlocked(so);
|
||||||
|
|
||||||
|
@ -593,8 +602,13 @@ rtm_sendup(struct socket *so, struct mbuf *m0)
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
|
|
||||||
|
mtx_enter(&so->so_rcv.sb_mtx);
|
||||||
if (sbspace(so, &so->so_rcv) < (2 * MSIZE) ||
|
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 */
|
/* Flag socket as desync'ed and flush required */
|
||||||
rop->rop_flags |= ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH;
|
rop->rop_flags |= ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH;
|
||||||
rtm_senddesync(so);
|
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.
|
* This file is in the public domain.
|
||||||
|
@ -340,7 +340,7 @@ int
|
||||||
addctag(char *s)
|
addctag(char *s)
|
||||||
{
|
{
|
||||||
struct ctag *t = NULL;
|
struct ctag *t = NULL;
|
||||||
char *l;
|
char *l, *c;
|
||||||
|
|
||||||
if ((t = malloc(sizeof(struct ctag))) == NULL) {
|
if ((t = malloc(sizeof(struct ctag))) == NULL) {
|
||||||
dobeep();
|
dobeep();
|
||||||
|
@ -357,6 +357,15 @@ addctag(char *s)
|
||||||
*l++ = '\0';
|
*l++ = '\0';
|
||||||
if (*l == '\0')
|
if (*l == '\0')
|
||||||
goto cleanup;
|
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));
|
t->pat = strip(l, strlen(l));
|
||||||
if (RB_INSERT(tagtree, &tags, t) != NULL) {
|
if (RB_INSERT(tagtree, &tags, t) != NULL) {
|
||||||
free(t);
|
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>.
|
.\" 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
|
.\" permitted provided that due credit is given to the author and the
|
||||||
.\" OpenBSD project by leaving this copyright notice intact.
|
.\" OpenBSD project by leaving this copyright notice intact.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: February 10 2023 $
|
.Dd $Mdocdate: June 14 2024 $
|
||||||
.Dt SSH-KEYSCAN 1
|
.Dt SSH-KEYSCAN 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
.Nd gather SSH public keys from servers
|
.Nd gather SSH public keys from servers
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm ssh-keyscan
|
.Nm ssh-keyscan
|
||||||
.Op Fl 46cDHv
|
.Op Fl 46cDHqv
|
||||||
.Op Fl f Ar file
|
.Op Fl f Ar file
|
||||||
.Op Fl O Ar option
|
.Op Fl O Ar option
|
||||||
.Op Fl p Ar port
|
.Op Fl p Ar port
|
||||||
|
@ -116,6 +116,9 @@ The default is to print both.
|
||||||
Connect to
|
Connect to
|
||||||
.Ar port
|
.Ar port
|
||||||
on the remote host.
|
on the remote host.
|
||||||
|
.It Fl q
|
||||||
|
Quiet mode:
|
||||||
|
do not print server host name and banners in comments.
|
||||||
.It Fl T Ar timeout
|
.It Fl T Ar timeout
|
||||||
Set the timeout for connection attempts.
|
Set the timeout for connection attempts.
|
||||||
If
|
If
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" 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 $
|
.\" $OpenBSD: ssh_config.5,v 1.395 2024/06/14 05:01:22 djm Exp $
|
||||||
.Dd $Mdocdate: February 21 2024 $
|
.Dd $Mdocdate: June 14 2024 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -1262,8 +1262,12 @@ it may be zero or more of:
|
||||||
and
|
and
|
||||||
.Cm skey .
|
.Cm skey .
|
||||||
.It Cm KexAlgorithms
|
.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.
|
Multiple algorithms must be comma-separated.
|
||||||
|
.Pp
|
||||||
If the specified list begins with a
|
If the specified list begins with a
|
||||||
.Sq +
|
.Sq +
|
||||||
character, then the specified algorithms will be appended to the default set
|
character, then the specified algorithms will be appended to the default set
|
||||||
|
@ -1276,6 +1280,7 @@ If the specified list begins with a
|
||||||
.Sq ^
|
.Sq ^
|
||||||
character, then the specified algorithms will be placed at the head of the
|
character, then the specified algorithms will be placed at the head of the
|
||||||
default set.
|
default set.
|
||||||
|
.Pp
|
||||||
The default is:
|
The default is:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
sntrup761x25519-sha512@openssh.com,
|
sntrup761x25519-sha512@openssh.com,
|
||||||
|
@ -1287,7 +1292,7 @@ diffie-hellman-group18-sha512,
|
||||||
diffie-hellman-group14-sha256
|
diffie-hellman-group14-sha256
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.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 .
|
.Qq ssh -Q kex .
|
||||||
.It Cm KnownHostsCommand
|
.It Cm KnownHostsCommand
|
||||||
Specifies a command to use to obtain a list of host keys, in addition to
|
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
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" 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 $
|
.\" $OpenBSD: sshd_config.5,v 1.363 2024/06/14 05:01:22 djm Exp $
|
||||||
.Dd $Mdocdate: June 13 2024 $
|
.Dd $Mdocdate: June 14 2024 $
|
||||||
.Dt SSHD_CONFIG 5
|
.Dt SSHD_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -1004,9 +1004,13 @@ file on logout.
|
||||||
The default is
|
The default is
|
||||||
.Cm yes .
|
.Cm yes .
|
||||||
.It Cm KexAlgorithms
|
.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.
|
Multiple algorithms must be comma-separated.
|
||||||
Alternately if the specified list begins with a
|
.Pp
|
||||||
|
If the specified list begins with a
|
||||||
.Sq +
|
.Sq +
|
||||||
character, then the specified algorithms will be appended to the default set
|
character, then the specified algorithms will be appended to the default set
|
||||||
instead of replacing them.
|
instead of replacing them.
|
||||||
|
@ -1018,6 +1022,7 @@ If the specified list begins with a
|
||||||
.Sq ^
|
.Sq ^
|
||||||
character, then the specified algorithms will be placed at the head of the
|
character, then the specified algorithms will be placed at the head of the
|
||||||
default set.
|
default set.
|
||||||
|
.Pp
|
||||||
The supported algorithms are:
|
The supported algorithms are:
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -item -compact -offset indent
|
.Bl -item -compact -offset indent
|
||||||
|
@ -1059,7 +1064,7 @@ diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,
|
||||||
diffie-hellman-group14-sha256
|
diffie-hellman-group14-sha256
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.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 .
|
.Qq ssh -Q KexAlgorithms .
|
||||||
.It Cm ListenAddress
|
.It Cm ListenAddress
|
||||||
Specifies the local addresses
|
Specifies the local addresses
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue