diff --git a/regress/Nsd.pm b/regress/Nsd.pm index 7c71194..a5f117d 100644 --- a/regress/Nsd.pm +++ b/regress/Nsd.pm @@ -34,7 +34,6 @@ sub new { $args{ktraceexec} = $ENV{KTRACE} if $ENV{KTRACE}; $args{ktracefile} ||= "nsd.ktrace"; $args{logfile} ||= "nsd.log"; - $args{serial} ||= time(); $args{up} ||= "nsd started"; my $self = Proc::new($class, %args); @@ -68,6 +67,16 @@ sub new { print $fh " name: regress.\n"; print $fh " zonefile: nsd.zone\n"; + return $self->zone(); +} + +sub zone { + my $self = shift; + my %args = @_; + $args{serial} ||= time(); + $self->{record_list} = $args{record_list} if $args{record_list}; + + my $test = basename($self->{testfile} || ""); open(my $fz, '>', "nsd.zone") or die ref($self), " zone file 'nsd.zone' create failed: $!"; print $fz "; test $test\n"; @@ -84,6 +93,10 @@ sub new { print $fz "$r\n"; } + kill('HUP', $self->{pid}) or die + ref($self), " kill HUP child '$self->{pid}' failed: $!" + if $args{sighup}; + return $self; } diff --git a/regress/Pfctl.pm b/regress/Pfctl.pm index c66580a..257ac78 100644 --- a/regress/Pfctl.pm +++ b/regress/Pfctl.pm @@ -54,6 +54,11 @@ sub child { } sub func { + my $self = shift; + $self->show(); +} + +sub show { my $self = shift; my @sudo = $ENV{SUDO} ? $ENV{SUDO} : (); diff --git a/regress/Pfresolved.pm b/regress/Pfresolved.pm index 2204f78..0b14f72 100644 --- a/regress/Pfresolved.pm +++ b/regress/Pfresolved.pm @@ -77,6 +77,7 @@ sub child { my @cmd = (@sudo, @ktrace, $self->{execfile}, "-dvvv", "-f", $self->{conffile}); push @cmd, "-r", $resolver if $resolver; + push @cmd, "-m", $self->{min_ttl} if $self->{min_ttl}; if ($self->{tls}) { my $ca = $self->{ca} || "ca.crt"; push @cmd, "-C", $ca if $self->{tls}; diff --git a/regress/args-ttl.pl b/regress/args-ttl.pl new file mode 100644 index 0000000..e47498e --- /dev/null +++ b/regress/args-ttl.pl @@ -0,0 +1,96 @@ +# Create zone file with A and AAAA records in zone regress. +# Start nsd with zone file with TTL 2 seconds and listening on 127.0.0.1. +# Write hosts of regress zone into pfresolved config. +# Start pfresolved with nsd as resolver. +# Wait until pfresolved creates table regress-pfresolved. +# Write new zone file with all adresses changed. +# Wait until TTL has expired and pfresolved has renewed adresses. +# Read IP addresses from pf table with pfctl. +# Check that pfresolved added IPv4 and IPv6 addresses. +# Check that pf table contains new IPv4 and IPv6 addresses with short TTL. +# Check that pf table contains old IPv4 and IPv6 addresses with default TTL. +# Check that pfresolved removed IPv4 and IPv6 addresses with short TTL. + +use strict; +use warnings; +use Socket; + +our %args = ( + nsd => { + listen => { domain => AF_INET, addr => "127.0.0.1" }, + record_list => [ + "foo A 192.0.2.1", + "bar AAAA 2001:DB8::1", + "foobar 2 A 192.0.2.2", + "foobar 2 AAAA 2001:DB8::2", + ], + loggrep => { + qr/listen on ip-address 127.0.0.1\@\d+ \(udp\)/ => 1, + qr/listen on ip-address [0-9A-Fa-f:]+\@\d+ / => 0, + }, + }, + pfresolved => { + address_list => [ map { "$_.regress." } qw(foo bar foobar) ], + min_ttl => 1, + loggrep => { + qr/-m 1/ => 1, + qr{added: 192.0.2.1/32,} => 1, + qr{added: 2001:db8::1/128,} => 1, + qr{added: 192.0.2.2/32,} => 1, + qr{added: 2001:db8::2/128,} => 1, + qr/starting new resolve request for .* in 3 seconds/ => 2, + qr{removed: 192.0.2.1/32} => 0, + qr{removed: 2001:db8::1/128} => 0, + qr{removed: 192.0.2.2/32$} => 1, + qr{removed: 2001:db8::2/128$} => 1, + qr{added: 192.0.2.10/32,} => 0, + qr{added: 2001:db8::10/128,} => 0, + qr{added: 192.0.2.20/32,} => 1, + qr{added: 2001:db8::20/128,} => 1, + }, + }, + pfctl => { + updated => [4, 1], + func => sub { + my $self = shift; + my $nsd = $self->{nsd}; + my $pfresolved = $self->{pfresolved}; + + $self->show(); + $nsd->zone( + record_list => [ + "foo A 192.0.2.10", + "bar AAAA 2001:DB8::10", + "foobar A 192.0.2.20", + "foobar AAAA 2001:DB8::20", + ], + sighup => 1, + ); + + # wait at most until TTL has expired + my $timeout = 3; + my ($updates, $deleted) = (2, 1); + my $table = + qr/updated addresses for pf table .*, deleted: $deleted,/; + my $tomsg = $timeout ? " after $timeout seconds" : ""; + my $upmsg = $updates ? " for $updates times" : ""; + $pfresolved->loggrep($table, $timeout, $updates) + or die ref($self), " no '$table' in $pfresolved->{logfile}", + $tomsg, $upmsg; + + $self->show(); + }, + loggrep => { + qr/^ 192.0.2.1$/ => 2, + qr/^ 192.0.2.2$/ => 1, + qr/^ 192.0.2.10$/ => 0, # foo not updated + qr/^ 192.0.2.20$/ => 1, # foobar updated after ttl expired + qr/^ 2001:db8::1$/ => 2, + qr/^ 2001:db8::2$/ => 1, + qr/^ 2001:db8::10$/ => 0, # foo not updated + qr/^ 2001:db8::20$/ => 1, # foobar updated after ttl expired + }, + }, +); + +1; diff --git a/regress/pfresolved.pl b/regress/pfresolved.pl index 7d3540a..78576ff 100644 --- a/regress/pfresolved.pl +++ b/regress/pfresolved.pl @@ -52,6 +52,7 @@ sub usage { ); my $s = Pfctl->new( %{$args{pfctl}}, + nsd => $n, pfresolved => $d, ) if $args{pfctl};