Download raw body.
pf af-to breaks traceroute
Hello Kristof,
I see the problem now. thanks for clarification. after slightly changing
my setup I can confirm OpenBSD current has the same bug. Fix below seems to
work for on OpenBSD. If I understand the issue right we need to combine 6to4
prefix defined in af-to rule with IPv4 source address seen in IP packet which
carries ICMPv4 error. I think your fix is very similar (modulo differences
between pf on FreeBSD and OpenBSD).
without the change I see output as follows when doing traceroute to 8.8.8.8
eco# traceroute6 -n 64:ff9b::8.8.8.8
traceroute6 to 64:ff9b::8.8.8.8 (64:ff9b::808:808), 64 hops max, 60 byte packets
1 fdd7:e83e:66bc:212:5054:ff:fe12:3450 2.243 ms 0.794 ms 0.711 ms
2 64:ff9b::808:808 2.629 ms 2.168 ms 2.133 ms
3 64:ff9b::808:808 2.029 ms 1.893 ms 2.01 ms
4 64:ff9b::808:808 2.622 ms 2.295 ms 2.305 ms
5 64:ff9b::808:808 3.025 ms 2.747 ms 2.893 ms
6 64:ff9b::808:808 15.597 ms 15.116 ms 17.987 ms
7 64:ff9b::808:808 18.331 ms 18.883 ms 18.402 ms
8 64:ff9b::808:808 19.619 ms 15.487 ms 18.181 ms
9 64:ff9b::808:808 20.157 ms 19.978 ms 17.597 ms
10 64:ff9b::808:808 22.123 ms 17.914 ms 21.457 ms
11 64:ff9b::808:808 19.044 ms 22.731 ms 25.352 ms
12 64:ff9b::808:808 26.151 ms 28.338 ms 23.295 ms
13 64:ff9b::808:808 22.159 ms 17.402 ms 19.978 ms
14 64:ff9b::808:808 23.1 ms 26.365 ms 21.514 ms
after applying the diff below the traceroute6 output changes to
eco# traceroute6 -n 64:ff9b::8.8.8.8
traceroute6 to 64:ff9b::8.8.8.8 (64:ff9b::808:808), 64 hops max, 60 byte packets
1 fdd7:e83e:66bc:212:5054:ff:fe12:3450 2.543 ms 0.891 ms 0.645 ms
2 64:ff9b::abc:d232 2.86 ms 1.869 ms 1.998 ms
3 64:ff9b::abc:d20a 2.076 ms 2.006 ms 2.182 ms
4 64:ff9b::ac10:101 2.501 ms 2.305 ms 2.331 ms
5 64:ff9b::c0a8:201 3.032 ms 2.893 ms 2.763 ms
6 64:ff9b::a29:3341 10.781 ms 10.214 ms 10.649 ms
7 64:ff9b::a26:3f1 9.739 ms 12.519 ms 10.337 ms
8 64:ff9b::a26:1df4 14.046 ms 10.423 ms 9.994 ms
9 64:ff9b::a26:fefc 10.478 ms 10.067 ms 11.771 ms
10 64:ff9b::b95b:a81b 14.762 ms 11.652 ms 12.617 ms
11 64:ff9b::b900:14aa 12.222 ms 13.247 ms 14.116 ms
12 64:ff9b::c0b2:6223 18.622 ms 11.917 ms 15.751 ms
13 64:ff9b::d8ef:2f0b 15.12 ms 64:ff9b::d8ef:38ef 12.11 ms 64:ff9b::d8ef:2f0b 11.728 ms
14 64:ff9b::808:808 12.841 ms 13.738 ms 12.305 ms
thank you for sharing all details here. very appreciated.
kind regards
sashan
--------8<---------------8<---------------8<------------------8<--------
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 6d6dbfd3c14..ce2cb7c2a9c 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -5650,6 +5650,16 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **stp,
if (afto) {
pf_addrcpy(&pd->nsaddr, &nk->addr[sidx],
nk->af);
+ if (nk->af == AF_INET6) {
+ /*
+ * IPv4 becomes IPv6 so we must put
+ * IPv4 src addr to least 32bits in
+ * IPv6 address to keep traceroute/icmp
+ * working.
+ */
+ pd->nsaddr.addr32[3] =
+ pd->src->addr32[0];
+ }
pf_addrcpy(&pd->ndaddr, &nk->addr[didx],
nk->af);
pd->naf = nk->af;
@@ -5925,17 +5935,27 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **stp,
pd, &pd2, &nk->addr[sidx],
&nk->addr[didx], pd->af, nk->af))
return (PF_DROP);
- if (nk->af == AF_INET)
- pd->proto = IPPROTO_ICMP;
- else
- pd->proto = IPPROTO_ICMPV6;
pd->m->m_pkthdr.ph_rtableid =
nk->rdomain;
pd->destchg = 1;
- pf_addrcpy(&pd->nsaddr,
- &nk->addr[pd2.sidx], nk->af);
pf_addrcpy(&pd->ndaddr,
&nk->addr[pd2.didx], nk->af);
+ pf_addrcpy(&pd->nsaddr,
+ &nk->addr[pd2.sidx], nk->af);
+ if (nk->af == AF_INET) {
+ pd->proto = IPPROTO_ICMP;
+ } else {
+ pd->proto = IPPROTO_ICMPV6;
+ /*
+ * IPv4 becomes IPv6 so we must
+ * put IPv4 src addr to least
+ * 32bits in IPv6 address to
+ * keep traceroute/icmp
+ * working.
+ */
+ pd->nsaddr.addr32[3] =
+ pd->src->addr32[0];
+ }
pd->naf = nk->af;
pf_patch_16(pd,
@@ -6045,17 +6065,27 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **stp,
pd, &pd2, &nk->addr[sidx],
&nk->addr[didx], pd->af, nk->af))
return (PF_DROP);
- if (nk->af == AF_INET)
- pd->proto = IPPROTO_ICMP;
- else
- pd->proto = IPPROTO_ICMPV6;
pd->m->m_pkthdr.ph_rtableid =
nk->rdomain;
pd->destchg = 1;
- pf_addrcpy(&pd->nsaddr,
- &nk->addr[pd2.sidx], nk->af);
pf_addrcpy(&pd->ndaddr,
&nk->addr[pd2.didx], nk->af);
+ pf_addrcpy(&pd->nsaddr,
+ &nk->addr[pd2.sidx], nk->af);
+ if (nk->af == AF_INET) {
+ pd->proto = IPPROTO_ICMP;
+ } else {
+ pd->proto = IPPROTO_ICMPV6;
+ /*
+ * IPv4 becomes IPv6 so we must
+ * put IPv4 src addr to least
+ * 32bits in IPv6 address to
+ * keep traceroute/icmp
+ * working.
+ */
+ pd->nsaddr.addr32[3] =
+ pd->src->addr32[0];
+ }
pd->naf = nk->af;
pf_patch_16(pd,
@@ -6182,10 +6212,24 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **stp,
pd->m->m_pkthdr.ph_rtableid =
nk->rdomain;
pd->destchg = 1;
- pf_addrcpy(&pd->nsaddr,
- &nk->addr[pd2.sidx], nk->af);
pf_addrcpy(&pd->ndaddr,
&nk->addr[pd2.didx], nk->af);
+ pf_addrcpy(&pd->nsaddr,
+ &nk->addr[pd2.sidx], nk->af);
+ if (nk->af == AF_INET) {
+ pd->proto = IPPROTO_ICMP;
+ } else {
+ pd->proto = IPPROTO_ICMPV6;
+ /*
+ * IPv4 becomes IPv6 so we must
+ * put IPv4 src addr to least
+ * 32bits in IPv6 address to
+ * keep traceroute/icmp
+ * working.
+ */
+ pd->nsaddr.addr32[3] =
+ pd->src->addr32[0];
+ }
pd->naf = nk->af;
return (PF_AFRT);
}
pf af-to breaks traceroute