Page MenuHomeFreeBSD

D40256.diff
No OneTemporary

D40256.diff

diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -136,7 +136,9 @@
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_sav), true,
"Drop incoming packets with source address that is a local address");
-VNET_DEFINE(pfil_head_t, inet_pfil_head); /* Packet filter hooks */
+/* Packet filter hooks */
+VNET_DEFINE(pfil_head_t, inet_pfil_head);
+VNET_DEFINE(pfil_head_t, inet_local_pfil_head);
static struct netisr_handler ip_nh = {
.nh_name = "ip",
@@ -327,6 +329,10 @@
args.pa_headname = PFIL_INET_NAME;
V_inet_pfil_head = pfil_head_register(&args);
+ args.pa_flags = PFIL_OUT;
+ args.pa_headname = PFIL_INET_LOCAL_NAME;
+ V_inet_local_pfil_head = pfil_head_register(&args);
+
if (hhook_head_register(HHOOK_TYPE_IPSEC_IN, AF_INET,
&V_ipsec_hhh_in[HHOOK_IPSEC_INET],
HHOOK_WAITOK | HHOOK_HEADISINVNET) != 0)
@@ -816,6 +822,20 @@
return;
#endif /* IPSTEALTH */
+ /*
+ * We are going to ship the packet to the local protocol stack. Call the
+ * filter again for this 'output' action, allowing redirect-like rules
+ * to adjust the source address.
+ */
+ if (PFIL_HOOKED_OUT(V_inet_local_pfil_head)) {
+ if (pfil_mbuf_out(V_inet_local_pfil_head, &m, V_loif, NULL) !=
+ PFIL_PASS)
+ return;
+ if (m == NULL) /* consumed by filter */
+ return;
+ ip = mtod(m, struct ip *);
+ }
+
/*
* Attempt reassembly; if it succeeds, proceed.
* ip_reass() will return a different mbuf.
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -255,6 +255,10 @@
#define V_inet_pfil_head VNET(inet_pfil_head)
#define PFIL_INET_NAME "inet"
+VNET_DECLARE(struct pfil_head *, inet_local_pfil_head);
+#define V_inet_local_pfil_head VNET(inet_local_pfil_head)
+#define PFIL_INET_LOCAL_NAME "inet-local"
+
void in_delayed_cksum(struct mbuf *m);
/* Hooks for ipfw, dummynet, divert etc. Most are declared in raw_ip.c */
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -208,6 +208,7 @@
#endif
VNET_DEFINE(pfil_head_t, inet6_pfil_head);
+VNET_DEFINE(pfil_head_t, inet6_local_pfil_head);
VNET_PCPUSTAT_DEFINE(struct ip6stat, ip6stat);
VNET_PCPUSTAT_SYSINIT(ip6stat);
@@ -245,6 +246,10 @@
args.pa_headname = PFIL_INET6_NAME;
V_inet6_pfil_head = pfil_head_register(&args);
+ args.pa_flags = PFIL_OUT;
+ args.pa_headname = PFIL_INET6_LOCAL_NAME;
+ V_inet6_local_pfil_head = pfil_head_register(&args);
+
if (hhook_head_register(HHOOK_TYPE_IPSEC_IN, AF_INET6,
&V_ipsec_hhh_in[HHOOK_IPSEC_INET6],
HHOOK_WAITOK | HHOOK_HEADISINVNET) != 0)
@@ -884,6 +889,20 @@
return;
}
+ /*
+ * We are going to ship the packet to the local protocol stack. Call the
+ * filter again for this 'output' action, allowing redirect-like rules
+ * to adjust the source address.
+ */
+ if (PFIL_HOOKED_OUT(V_inet6_local_pfil_head)) {
+ if (pfil_mbuf_out(V_inet6_local_pfil_head, &m, V_loif, NULL) !=
+ PFIL_PASS)
+ return;
+ if (m == NULL) /* consumed by filter */
+ return;
+ ip6 = mtod(m, struct ip6_hdr *);
+ }
+
/*
* Tell launch routine the next header
*/
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -325,6 +325,10 @@
#define V_inet6_pfil_head VNET(inet6_pfil_head)
#define PFIL_INET6_NAME "inet6"
+VNET_DECLARE(struct pfil_head *, inet6_local_pfil_head);
+#define V_inet6_local_pfil_head VNET(inet6_local_pfil_head)
+#define PFIL_INET6_LOCAL_NAME "inet6-local"
+
#ifdef IPSTEALTH
VNET_DECLARE(int, ip6stealth);
#define V_ip6stealth VNET(ip6stealth)
diff --git a/tests/sys/netpfil/common/Makefile b/tests/sys/netpfil/common/Makefile
--- a/tests/sys/netpfil/common/Makefile
+++ b/tests/sys/netpfil/common/Makefile
@@ -9,6 +9,7 @@
dummynet \
pass_block \
nat \
+ rdr \
tos \
fragments \
forward
diff --git a/tests/sys/netpfil/pf/rdr.sh b/tests/sys/netpfil/common/rdr.sh
rename from tests/sys/netpfil/pf/rdr.sh
rename to tests/sys/netpfil/common/rdr.sh
--- a/tests/sys/netpfil/pf/rdr.sh
+++ b/tests/sys/netpfil/common/rdr.sh
@@ -26,17 +26,19 @@
# SUCH DAMAGE.
. $(atf_get_srcdir)/utils.subr
+. $(atf_get_srcdir)/runner.subr
-atf_test_case "basic" "cleanup"
basic_head()
{
- atf_set descr 'Basic rdr test'
+ atf_set descr 'Basic IPv4 NAT test'
atf_set require.user root
}
basic_body()
{
- pft_init
+ firewall=$1
+ firewall_init $firewall
+ nat_init $firewall
epair=$(vnet_mkepair)
@@ -48,10 +50,13 @@
jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up
jexec alcatraz sysctl net.inet.ip.forwarding=1
- # Enable pf!
- jexec alcatraz pfctl -e
- pft_set_rules alcatraz \
- "rdr pass on ${epair}b proto tcp from any to 198.51.100.0/24 port 1234 -> 192.0.2.1 port 4321"
+ # Enable redirect filter rule
+ firewall_config alcatraz ${firewall} \
+ "pf" \
+ "rdr pass on ${epair}b proto tcp from any to 198.51.100.0/24 port 1234 -> 192.0.2.1 port 4321" \
+ "ipfnat" \
+ "rdr ${epair}b from any to 198.51.100.0/24 port = 1234 -> 192.0.2.1 port 4321 tcp"
+
echo "foo" | jexec alcatraz nc -N -l 4321 &
sleep 1
@@ -64,10 +69,69 @@
basic_cleanup()
{
- pft_cleanup
+ firewall=$1
+ firewall_cleanup $firewall
}
-atf_init_test_cases()
+local_redirect_head()
{
- atf_add_test_case "basic"
+ atf_set descr 'Redirect local traffic test'
+ atf_set require.user root
}
+
+local_redirect_body()
+{
+ firewall=$1
+ firewall_init $firewall
+ nat_init $firewall
+
+ bridge=$(vnet_mkbridge)
+ ifconfig ${bridge} 192.0.2.1/24 up
+
+ epair1=$(vnet_mkepair)
+ epair2=$(vnet_mkepair)
+
+ vnet_mkjail first ${epair1}b
+ ifconfig ${epair1}a up
+ ifconfig ${bridge} addm ${epair1}a
+ jexec first ifconfig ${epair1}b 192.0.2.2/24 up
+ jexec first ifconfig lo0 127.0.0.1/8 up
+
+ vnet_mkjail second ${epair2}b
+ ifconfig ${epair2}a up
+ ifconfig ${bridge} addm ${epair2}a
+ jexec second ifconfig ${epair2}b 192.0.2.3/24 up
+ jexec second ifconfig lo0 127.0.0.1/8 up
+ jexec second sysctl net.inet.ip.forwarding=1
+
+ # Enable redirect filter rule
+ firewall_config second ${firewall} \
+ "pf" \
+ "rdr pass proto tcp from any to 192.0.2.3/24 port 1234 -> 192.0.2.2 port 4321" \
+ "ipfnat" \
+ "rdr '*' from any to 192.0.2.3/24 port = 1234 -> 192.0.2.2 port 4321 tcp"
+
+ echo "foo" | jexec first nc -N -l 4321 &
+ sleep 1
+
+ # Verify that second can use its rule to redirect local connections to first
+ result=$(jexec second nc -N -w 3 192.0.2.3 1234)
+ if [ "$result" != "foo" ]; then
+ atf_fail "Redirect failed"
+ fi
+}
+
+local_redirect_cleanup()
+{
+ firewall=$1
+ firewall_cleanup $firewall
+}
+
+setup_tests \
+ basic \
+ pf \
+ ipfnat \
+ local_redirect \
+ pf \
+ ipfnat
+
diff --git a/tests/sys/netpfil/common/utils.subr b/tests/sys/netpfil/common/utils.subr
--- a/tests/sys/netpfil/common/utils.subr
+++ b/tests/sys/netpfil/common/utils.subr
@@ -58,12 +58,16 @@
jexec ${jname} pfctl -e
jexec ${jname} pfctl -F all
jexec ${jname} pfctl -f $cwd/pf.rule
+ jexec ${jname} pfilctl link -o pf:default-out inet-local
+ jexec ${jname} pfilctl link -o pf:default-out6 inet6-local
elif [ ${fw} == "ipf" ]; then
jexec ${jname} ipf -E
jexec ${jname} ipf -Fa -f $cwd/ipf.rule
elif [ ${fw} == "ipfnat" ]; then
jexec ${jname} service ipfilter start
jexec ${jname} ipnat -CF -f $cwd/ipfnat.rule
+ jexec ${jname} pfilctl link -o ipfilter:default-ip4 inet-local
+ jexec ${jname} pfilctl link -o ipfilter:default-ip6 inet6-local
else
atf_fail "$fw is not a valid firewall to configure"
fi
diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile
--- a/tests/sys/netpfil/pf/Makefile
+++ b/tests/sys/netpfil/pf/Makefile
@@ -25,7 +25,6 @@
pfsync \
prio \
proxy \
- rdr \
ridentifier \
route_to \
rtable \

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 10, 10:02 AM (1 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15741627
Default Alt Text
D40256.diff (7 KB)

Event Timeline