diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-02-28 16:16:11 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-02-28 16:16:11 +0000 |
commit | fa35b09d6b1e3dd78046d5654ecf909b32a652ed (patch) | |
tree | d4f1a4239414e2c03a22c1bb9af2c20867b0f30a /sys/netinet | |
parent | aeaad68af7fd0f6faa184ee993c354cf819359e2 (diff) |
When IPsec UDP encapsulation is used for IPv6, the stack should
construct an IPv6 packet instead of an IPv4.
Diff from Patrick Wildt <patrick at blueri ! se> with input from
bluhm@; ok mpi, bluhm
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ipsec_output.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/sys/netinet/ipsec_output.c b/sys/netinet/ipsec_output.c index 91c319fd403..10119faccc9 100644 --- a/sys/netinet/ipsec_output.c +++ b/sys/netinet/ipsec_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec_output.c,v 1.61 2015/09/11 08:17:06 claudio Exp $ */ +/* $OpenBSD: ipsec_output.c,v 1.62 2016/02/28 16:16:10 mikeb Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * @@ -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,12 @@ 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) + m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; +#endif /* INET6 */ espstat.esps_udpencout++; } |