Page MenuHomeFreeBSD

D60542.diff
No OneTemporary

D60542.diff

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -8753,9 +8753,21 @@
&pd->hdr.icmp6.icmp6_cksum,
&nk->addr[didx], 0);
- if (nk->port[iidx] != pd->hdr.icmp6.icmp6_id)
+ /*
+ * Only echo has an identifier. Other
+ * types use a virtual id of 0 and keep
+ * other fields here (e.g. the NA flags).
+ */
+ if (virtual_type == htons(ICMP6_ECHO_REQUEST) &&
+ nk->port[iidx] != pd->hdr.icmp6.icmp6_id) {
+ pd->hdr.icmp6.icmp6_cksum =
+ pf_cksum_fixup(
+ pd->hdr.icmp6.icmp6_cksum,
+ pd->hdr.icmp6.icmp6_id,
+ nk->port[iidx], 0);
pd->hdr.icmp6.icmp6_id =
nk->port[iidx];
+ }
m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr),
(caddr_t )&pd->hdr.icmp6);
diff --git a/tests/sys/netpfil/pf/icmp6.sh b/tests/sys/netpfil/pf/icmp6.sh
--- a/tests/sys/netpfil/pf/icmp6.sh
+++ b/tests/sys/netpfil/pf/icmp6.sh
@@ -196,9 +196,82 @@
pft_cleanup
}
+atf_test_case "nat_nud" "cleanup"
+nat_nud_head()
+{
+ atf_set descr 'Test that NUD works when pf translates the probes'
+ atf_set require.user root
+}
+
+nat_nud_body()
+{
+ pft_init
+
+ epair=$(vnet_mkepair)
+
+ vnet_mkjail alcatraz ${epair}a
+ jexec alcatraz ifconfig ${epair}a inet6 no_dad
+ jexec alcatraz ifconfig ${epair}a inet6 2001:db8::1/64 up
+ # Probe a stale neighbour one second after using it, not five.
+ jexec alcatraz sysctl net.inet6.icmp6.nd6_delay=1
+
+ vnet_mkjail singsing ${epair}b
+ jexec singsing ifconfig ${epair}b inet6 no_dad
+ jexec singsing ifconfig ${epair}b inet6 2001:db8::2/64 up
+
+ lla=$(jexec alcatraz ifconfig ${epair}a inet6 | \
+ awk '/fe80:/ { sub(/%.*/, "", $2); print $2 }')
+ llb=$(jexec singsing ifconfig ${epair}b inet6 | \
+ awk '/fe80:/ { sub(/%.*/, "", $2); print $2 }')
+
+ # NUD probes are sent from the link-local address, so this translates
+ # them, and the advertisements answering them come back to 2001:db8::1.
+ jexec alcatraz pfctl -e
+ pft_set_rules alcatraz \
+ "nat on ${epair}a inet6 from fe80::/10 to any -> 2001:db8::1" \
+ "pass"
+
+ # singsing resolving alcatraz leaves it stale in alcatraz's neighbour
+ # cache, and alcatraz answering uses it, so alcatraz will probe it.
+ atf_check -s exit:0 -o ignore \
+ jexec singsing ping -6 -c 1 ${lla}%${epair}b
+
+ # The advertisement answering the probe makes the neighbour reachable.
+ # A corrupted one is dropped: alcatraz probes twice more, then deletes
+ # the entry.
+ state=
+ for i in $(seq 1 15); do
+ state=$(jexec alcatraz ndp -n ${llb}%${epair}a 2>/dev/null | \
+ awk 'NR == 2 { print $5 }')
+ if [ "${state}" = "R" ]; then
+ break
+ fi
+ sleep 1
+ done
+
+ jexec alcatraz ndp -an
+ jexec alcatraz pfctl -ss -vv
+
+ if [ "${state}" != "R" ]; then
+ atf_fail "NUD failed, neighbour state '${state:-no entry}'"
+ fi
+ atf_check -o match:"^[[:space:]]*0 bad checksums$" \
+ jexec alcatraz netstat -s -p icmp6
+
+ # The probe was translated
+ atf_check -o match:"2001:db8::1 \(${lla}\) -> ${llb}\[135\]" \
+ jexec alcatraz pfctl -ss
+}
+
+nat_nud_cleanup()
+{
+ pft_cleanup
+}
+
atf_init_test_cases()
{
atf_add_test_case "zero_id"
atf_add_test_case "ttl_exceeded"
atf_add_test_case "repeat"
+ atf_add_test_case "nat_nud"
}

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 11, 3:25 AM (9 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40568895
Default Alt Text
D60542.diff (3 KB)

Event Timeline