diff options
author | 2011-12-19 02:43:19 +0000 | |
---|---|---|
committer | 2011-12-19 02:43:19 +0000 | |
commit | 6ba2612f351a784261aea42d6e28a36a27084833 (patch) | |
tree | 0de68212bf17a3525d98f42262ad32a90e846416 /sys/netinet/ipsec_input.c | |
parent | Improvements from kristaps@: (diff) | |
download | wireguard-openbsd-6ba2612f351a784261aea42d6e28a36a27084833.tar.xz wireguard-openbsd-6ba2612f351a784261aea42d6e28a36a27084833.zip |
Fix checksum of UDP/TCP packets following RFC 3948. This is required for
transport mode IPsec NAT-T.
ok markus
Diffstat (limited to 'sys/netinet/ipsec_input.c')
-rw-r--r-- | sys/netinet/ipsec_input.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c index 031a14141b1..226399271a6 100644 --- a/sys/netinet/ipsec_input.c +++ b/sys/netinet/ipsec_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec_input.c,v 1.103 2011/04/26 22:30:38 bluhm Exp $ */ +/* $OpenBSD: ipsec_input.c,v 1.104 2011/12/19 02:43:19 yasuoka Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -557,6 +557,53 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff, #endif /* INET6 */ /* + * Fix TCP/UDP checksum of UDP encapsulated transport mode ESP packet. + * (RFC3948 3.1.1) + */ + if ((af == AF_INET || af == AF_INET6) && + (tdbp->tdb_flags & TDBF_UDPENCAP) && + (tdbp->tdb_flags & TDBF_TUNNELING) == 0) { + u_int16_t cksum; + + switch (prot) { + case IPPROTO_UDP: + if (m->m_pkthdr.len < skip + sizeof(struct udphdr)) { + m_freem(m); + IPSEC_ISTAT(espstat.esps_hdrops, + ahstat.ahs_hdrops, + ipcompstat.ipcomps_hdrops); + return EINVAL; + } + cksum = 0; + m_copyback(m, skip + offsetof(struct udphdr, uh_sum), + sizeof(cksum), &cksum, M_NOWAIT); + break; + case IPPROTO_TCP: + if (m->m_pkthdr.len < skip + sizeof(struct tcphdr)) { + m_freem(m); + IPSEC_ISTAT(espstat.esps_hdrops, + ahstat.ahs_hdrops, + ipcompstat.ipcomps_hdrops); + return EINVAL; + } + cksum = 0; + m_copyback(m, skip + offsetof(struct tcphdr, th_sum), + sizeof(cksum), &cksum, M_NOWAIT); + if (af == AF_INET) + cksum = in4_cksum(m, IPPROTO_TCP, skip, + m->m_pkthdr.len - skip); +#ifdef INET6 + else if (af == AF_INET6) + cksum = in6_cksum(m, IPPROTO_TCP, skip, + m->m_pkthdr.len - skip); +#endif + m_copyback(m, skip + offsetof(struct tcphdr, th_sum), + sizeof(cksum), &cksum, M_NOWAIT); + break; + } + } + + /* * Record what we've done to the packet (under what SA it was * processed). If we've been passed an mtag, it means the packet * was already processed by an ethernet/crypto combo card and |