Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for negated addresses #40

Merged
merged 2 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Revision history for pfresolved pf table DNS update daemon

1.01
* Add support for negated addresses.

1.00 2023-11-24
* Initial public release.
36 changes: 31 additions & 5 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ static struct pfresolved_table *cur_table = NULL;
int add_table_value(struct pfresolved_table *,
const char *);
int add_static_address(struct pfresolved_table *,
const char *);
const char *, int);
int add_host(struct pfresolved_table *,
const char *);
struct pfresolved_table *table_lookup_or_create(const char *);
Expand Down Expand Up @@ -166,6 +166,15 @@ table_values : /* empty */
}
free($2);
}
| table_values '!' table_value optcomma optnl
{
if (add_static_address(cur_table, $3, 1) == -1) {
yyerror("add_static_address failed");
free($3);
YYERROR;
}
free($3);
}
;

table_name : STRING
Expand Down Expand Up @@ -728,15 +737,15 @@ add_table_value(struct pfresolved_table *table, const char *value)
if (!table)
return (-1);

if (add_static_address(table, value) == -1 &&
if (add_static_address(table, value, 0) == -1 &&
add_host(table, value) == -1)
return (-1);

return (0);
}

int
add_static_address(struct pfresolved_table *table, const char *value)
add_static_address(struct pfresolved_table *table, const char *value, int negate)
{
struct pfresolved_table_entry *entry, *old;
struct in_addr in4;
Expand All @@ -750,12 +759,22 @@ add_static_address(struct pfresolved_table *table, const char *value)
fatal("%s: calloc", __func__);

if ((bits = inet_net_pton(AF_INET, value, &in4, sizeof(in4))) != -1) {
if (negate && bits != 32) {
yyerror("negation is not allowed for networks");
free(entry);
return (-1);
}
applymask4(&in4, bits);
entry->pfte_addr.pfa_af = AF_INET;
entry->pfte_addr.pfa_addr.in4 = in4;
entry->pfte_addr.pfa_prefixlen = bits;
} else if ((bits = inet_net_pton(AF_INET6, value, &in6,
sizeof(in6))) != -1) {
if (negate && bits != 128) {
yyerror("negation is not allowed for networks");
free(entry);
return (-1);
}
applymask6(&in6, bits);
entry->pfte_addr.pfa_af = AF_INET6;
entry->pfte_addr.pfa_addr.in6 = in6;
Expand All @@ -766,12 +785,19 @@ add_static_address(struct pfresolved_table *table, const char *value)
}

entry->pfte_static = 1;
entry->pfte_negate = negate;

old = RB_INSERT(pfresolved_table_entries, &table->pft_entries, entry);
if (old) {
free(entry);
log_warn("duplicate entry in config: %s %s", table->pft_name,
value);
if (old->pfte_negate != negate) {
yyerror("the same address cannot be specified in normal"
" and negated form");
return (-1);
} else {
log_warn("duplicate entry in config: %s %s",
table->pft_name, value);
}
}
return (0);
}
Expand Down
6 changes: 5 additions & 1 deletion pfresolved.conf.5
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,12 @@ it will be created by
A list of hostnames that should be resolved by
.Xr pfresolved 8
for the specified table.
The list can also contain IP addresses.
The list can also contain IP addresses and networks.
These will be directly added to the table when the configuration
file is loaded.
IP addresses can also be negated by prefixing them with the
.Cm !\&
operator.
Entries in the list may be separated by comma or newline.
.El
.Sh EXAMPLES
Expand All @@ -99,6 +102,7 @@ myTable2 {
example.net
example.org
198.51.100.0
! 198.51.100.1
include "/list/with/hosts"
}
.Ed
Expand Down
1 change: 1 addition & 0 deletions pfresolved.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ struct pfresolved_address {
struct pfresolved_table_entry {
struct pfresolved_address pfte_addr;
int pfte_static;
int pfte_negate;
int pfte_refcount;
RB_ENTRY(pfresolved_table_entry) pfte_node;
};
Expand Down
1 change: 1 addition & 0 deletions pftable.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pftable_set_addresses(struct pfresolved *env, struct pfresolved_table *table)
buffer[count].pfra_ip6addr = entry->pfte_addr.pfa_addr.in6;
}
buffer[count].pfra_net = entry->pfte_addr.pfa_prefixlen;
buffer[count].pfra_not = entry->pfte_negate;
count++;
}

Expand Down
4 changes: 3 additions & 1 deletion regress/Proc.pm
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,11 @@ sub loggrep {
my $end;
$end = time() + $timeout if $timeout;

my $expected_status = $self->{expected_status} || 0;

do {
my($kid, $status, $code) = $self->wait(WNOHANG);
if ($kid > 0 && $status != 0) {
if ($kid > 0 && $status != $expected_status << 8) {
# child terminated with failure
die ref($self), " child status: $status $code";
}
Expand Down
44 changes: 44 additions & 0 deletions regress/args-negated-address.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Create zone file with A and AAAA records in zone regress.
# Start nsd with zone file listening on 127.0.0.1.
# Write hosts of regress zone into pfresolved config.
# Write negated addresses for hosts in regress zone into pfresolved config.
# Start pfresolved with nsd as resolver.
# Wait until pfresolved creates table regress-pfresolved.
# Read IP addresses from pf table with pfctl.
# Check that pfresolved resolved IPv4 and IPv6 addresses.
# Check that pf table only contains the negated IPv4 and IPv6 addresses.

use strict;
use warnings;
use Socket;

our %args = (
nsd => {
record_list => [
"foo IN A 192.0.2.1",
"foo IN AAAA 2001:DB8::1",
],
},
pfresolved => {
address_list => [
"foo.regress.",
"! 192.0.2.1",
"! 2001:DB8::1",
],
loggrep => {
qr{added: 192.0.2.1/32,} => 1,
qr{added: 2001:db8::1/128,} => 1,
},
},
pfctl => {
updated => [2, 0],
loggrep => {
qr/^ !192.0.2.1$/ => 1,
qr/^ 192.0.2.1$/ => 0,
qr/^ !2001:db8::1$/ => 1,
qr/^ 2001:db8::1$/ => 0,
},
},
);

1;
22 changes: 22 additions & 0 deletions regress/args-negated-network.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Write negated network into pfresolved config.
# Start pfresolved.
# Check that configuration parsing fails.

use strict;
use warnings;
use Socket;

our %args = (
pfresolved => {
address_list => [
"! 192.0.2.1/24",
],
loggrep => {
qr{negation is not allowed for networks} => 1,
},
expected_status => 1,
down => "parent: parsing configuration failed",
},
);

1;
23 changes: 23 additions & 0 deletions regress/args-normal-and-negated-address.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Write the same address in normal and negated form into pfresolved config.
# Start pfresolved.
# Check that configuration parsing fails.

use strict;
use warnings;
use Socket;

our %args = (
pfresolved => {
address_list => [
"192.0.2.1",
"! 192.0.2.1",
],
loggrep => {
qr{the same address cannot be specified in normal and negated form} => 1,
},
expected_status => 1,
down => "parent: parsing configuration failed",
},
);

1;
Loading