Bump with updated diff, now that tree is unlocked again.
Patrick
diff --git sys/netinet/ipsec_output.c sys/netinet/ipsec_output.c
index 91c319f..18a3f57 100644
--- sys/netinet/ipsec_output.c
+++ sys/netinet/ipsec_output.c
@@ -375,13 +375,30 @@ ipsp_process_done(struct mbuf *m, struct tdb *tdb)
if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) {
struct mbuf *mi;
struct udphdr *uh;
+ int iphlen;
if (!udpencap_enable || !udpencap_port) {
m_freem(m);
return ENXIO;
}
- mi = m_inject(m, sizeof(struct ip), sizeof(struct udphdr),
- M_DONTWAIT);
+
+ switch (tdb->tdb_dst.sa.sa_family) {
+ case AF_INET:
+ iphlen = sizeof(struct ip);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ iphlen = sizeof(struct ip6_hdr);
+ break;
+#endif /* INET6 */
+ default:
+ m_freem(m);
+ DPRINTF(("ipsp_process_done(): unknown protocol family "
+ "(%d)\n", tdb->tdb_dst.sa.sa_family));
+ return ENXIO;
+ }
+
+ mi = m_inject(m, iphlen, sizeof(struct udphdr), M_DONTWAIT);
if (mi == NULL) {
m_freem(m);
return ENOMEM;
@@ -391,8 +408,13 @@ ipsp_process_done(struct mbuf *m, struct tdb *tdb)
if (tdb->tdb_udpencap_port)
uh->uh_dport = tdb->tdb_udpencap_port;
- uh->uh_ulen = htons(m->m_pkthdr.len - sizeof(struct ip));
+ uh->uh_ulen = htons(m->m_pkthdr.len - iphlen);
uh->uh_sum = 0;
+#ifdef INET6
+ if (tdb->tdb_dst.sa.sa_family == AF_INET6)
+ uh->uh_sum = in6_cksum(m, IPPROTO_UDP,
+ iphlen, m->m_pkthdr.len - iphlen);
+#endif /* INET6 */
espstat.esps_udpencout++;
}
On Sun, Feb 21, 2016 at 09:14:13PM +0100, Patrick Wildt wrote:
> Hi,
>
> debugging my setup at home I realized that NAT-T on IPv6 is broken.
> I know that NAT in IPv6 sucks, but apparently my dsl modem does not
> reliably forward ESP packets, so I use NAT-T instead... *sigh*
>
> Moving that setup from IPv4 to IPv6 I noticed that pf was blocking
> outgoing packets and its src/dst addresses were broken. Digging
> in the code I saw that the UDP header injection is written only
> for IPv4.
>
> This diff was written for and tested on OpenBSD 5.8, then ported
> to -current. The only difference in the tested diff and this
> diff is that m_makespace() was replaced by m_inject().
>
> Patrick
>
> diff --git sys/netinet/ipsec_output.c sys/netinet/ipsec_output.c
> index 91c319f..372d8d4 100644
> --- sys/netinet/ipsec_output.c
> +++ sys/netinet/ipsec_output.c
> @@ -375,13 +375,30 @@ ipsp_process_done(struct mbuf *m, struct tdb *tdb)
> if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) {
> struct mbuf *mi;
> struct udphdr *uh;
> + int iphlen;
>
> if (!udpencap_enable || !udpencap_port) {
> m_freem(m);
> return ENXIO;
> }
> - mi = m_inject(m, sizeof(struct ip), sizeof(struct udphdr),
> - M_DONTWAIT);
> +
> + switch (tdb->tdb_dst.sa.sa_family) {
> + case AF_INET:
> + iphlen = sizeof(struct ip);
> + break;
> +#ifdef INET6
> + case AF_INET6:
> + iphlen = sizeof(struct ip6_hdr);
> + break;
> +#endif /* INET6 */
> + default:
> + m_freem(m);
> + DPRINTF(("ipsp_process_done(): unknown protocol family
> (%d)\n",
> + tdb->tdb_dst.sa.sa_family));
> + return ENXIO;
> + }
> +
> + mi = m_inject(m, iphlen, sizeof(struct udphdr), M_DONTWAIT);
> if (mi == NULL) {
> m_freem(m);
> return ENOMEM;
> @@ -391,8 +408,11 @@ ipsp_process_done(struct mbuf *m, struct tdb *tdb)
> if (tdb->tdb_udpencap_port)
> uh->uh_dport = tdb->tdb_udpencap_port;
>
> - uh->uh_ulen = htons(m->m_pkthdr.len - sizeof(struct ip));
> + uh->uh_ulen = htons(m->m_pkthdr.len - iphlen);
> uh->uh_sum = 0;
> + if (tdb->tdb_dst.sa.sa_family == AF_INET6)
> + uh->uh_sum = in6_cksum(m, IPPROTO_UDP,
> + iphlen, m->m_pkthdr.len - iphlen);
> espstat.esps_udpencout++;
> }
>