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++; > } >