Page MenuHomeFreeBSD

D53216.id164676.diff
No OneTemporary

D53216.id164676.diff

diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -5384,9 +5384,20 @@
yyerror("nat-to and rdr-to require keep state");
problems++;
}
- if (r->direction == PF_INOUT) {
- yyerror("nat-to and rdr-to require a direction");
- problems++;
+ }
+ if (!(r->rule_flag & PFRULE_AFTO)) {
+ /* XXX: Do af-to rule require direction? */
+ if (!TAILQ_EMPTY(&(r->nat.list))) {
+ if (r->direction != PF_OUT) {
+ yyerror("nat-to can only be used with direction out");
+ problems++;
+ }
+ }
+ if (!TAILQ_EMPTY(&(r->rdr.list))) {
+ if (r->direction != PF_IN) {
+ yyerror("rdr-to can only be used with direction in");
+ problems++;
+ }
}
}
if (r->route.opts & PF_POOL_STICKYADDR && !r->keep_state) {
diff --git a/sbin/pfctl/tests/files/pf1076.fail b/sbin/pfctl/tests/files/pf1076.fail
new file mode 100644
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1076.fail
@@ -0,0 +1 @@
+rdr-to can only be used with direction in
diff --git a/sbin/pfctl/tests/files/pf1076.in b/sbin/pfctl/tests/files/pf1076.in
new file mode 100644
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1076.in
@@ -0,0 +1 @@
+pass out on lo0 from any rdr-to 2001:db8::1
diff --git a/sbin/pfctl/tests/files/pf1077.fail b/sbin/pfctl/tests/files/pf1077.fail
new file mode 100644
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1077.fail
@@ -0,0 +1 @@
+nat-to can only be used with direction out
diff --git a/sbin/pfctl/tests/files/pf1077.in b/sbin/pfctl/tests/files/pf1077.in
new file mode 100644
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1077.in
@@ -0,0 +1 @@
+pass in on lo0 from any nat-to 2001:db8::1
diff --git a/sbin/pfctl/tests/pfctl_test_list.inc b/sbin/pfctl/tests/pfctl_test_list.inc
--- a/sbin/pfctl/tests/pfctl_test_list.inc
+++ b/sbin/pfctl/tests/pfctl_test_list.inc
@@ -184,3 +184,5 @@
PFCTL_TEST(1073, "Filter AF different than route-to AF, with prefer-ipv6-nexthop")
PFCTL_TEST_FAIL(1074, "Filter AF different than route-to AF, without prefer-ipv6-nexthop")
PFCTL_TEST(1075, "One shot rule")
+PFCTL_TEST_FAIL(1076, "rdr-to can only be used with direction in")
+PFCTL_TEST_FAIL(1077, "nat-to can only be used with direction out")
diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -974,6 +974,7 @@
{
struct pf_pdesc *pd = ctx->pd;
struct pf_addr *naddr;
+ int idx;
uint16_t *nportp;
uint16_t low, high;
u_short reason;
@@ -988,8 +989,19 @@
return (PFRES_MEMORY);
}
- naddr = &ctx->nk->addr[1];
- nportp = &ctx->nk->port[1];
+ switch (nat_action) {
+ case PF_NAT:
+ idx = pd->sidx;
+ break;
+ case PF_BINAT:
+ idx = 1;
+ break;
+ case PF_RDR:
+ idx = pd->didx;
+ break;
+ }
+ naddr = &ctx->nk->addr[idx];
+ nportp = &ctx->nk->port[idx];
switch (nat_action) {
case PF_NAT:
diff --git a/tests/sys/netpfil/pf/nat.sh b/tests/sys/netpfil/pf/nat.sh
--- a/tests/sys/netpfil/pf/nat.sh
+++ b/tests/sys/netpfil/pf/nat.sh
@@ -477,15 +477,49 @@
pft_cleanup
}
-atf_test_case "nat_pass" "cleanup"
-nat_pass_head()
+atf_test_case "nat_pass_in" "cleanup"
+nat_pass_in_head()
{
- atf_set descr 'IPv4 NAT on pass rule'
+ atf_set descr 'IPv4 NAT on inbound pass rule'
atf_set require.user root
atf_set require.progs scapy
}
-nat_pass_body()
+nat_pass_in_body()
+{
+ setup_router_server_ipv4
+ # Delete the route back to make sure that the traffic has been NAT-ed
+ jexec server route del -net ${net_tester} ${net_server_host_router}
+ # Provide routing back to the NAT address
+ jexec server route add 203.0.113.0/24 ${net_server_host_router}
+ jexec router route add 203.0.113.0/24 -iface ${epair_tester}b
+
+ pft_set_rules router \
+ "block" \
+ "pass in on ${epair_tester}b inet proto tcp nat-to 203.0.113.0 keep state" \
+ "pass out on ${epair_server}a inet proto tcp keep state"
+
+ ping_server_check_reply exit:0 --ping-type=tcp3way --send-sport=4201
+
+ jexec router pfctl -qvvsr
+ jexec router pfctl -qvvss
+ jexec router ifconfig
+ jexec router netstat -rn
+}
+
+nat_pass_in_cleanup()
+{
+ pft_cleanup
+}
+
+nat_pass_out_head()
+{
+ atf_set descr 'IPv4 NAT on outbound pass rule'
+ atf_set require.user root
+ atf_set require.progs scapy
+}
+
+nat_pass_out_body()
{
setup_router_server_ipv4
# Delete the route back to make sure that the traffic has been NAT-ed
@@ -504,7 +538,7 @@
jexec router netstat -rn
}
-nat_pass_cleanup()
+nat_pass_out_cleanup()
{
pft_cleanup
}
@@ -874,10 +908,14 @@
atf_add_test_case "no_addrs_random"
atf_add_test_case "map_e_compat"
atf_add_test_case "map_e_pass"
- atf_add_test_case "nat_pass"
+ atf_add_test_case "nat_pass_out"
atf_add_test_case "nat_match"
atf_add_test_case "binat_compat"
atf_add_test_case "binat_match"
atf_add_test_case "empty_pool"
atf_add_test_case "dummynet_mask"
+
+ # Skip this case: pfctl only allows nat-to on outbound rules even though
+ # kernel code properly nats and rdrs in the opposite direction.
+ # atf_add_test_case "nat_pass_in"
}

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 4, 10:31 PM (49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29258031
Default Alt Text
D53216.id164676.diff (4 KB)

Event Timeline