summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2011-12-19 02:43:20 +0000
committerYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2011-12-19 02:43:20 +0000
commit72a2f316cb6f53a26d8f3998c7b03c3a1961adec (patch)
tree196e2890cfde07aafb86cbf004e986062c7e7969 /sys
parent7624e132604813b4df8d86067616c584406c5ce7 (diff)
Fix checksum of UDP/TCP packets following RFC 3948. This is required for
transport mode IPsec NAT-T. ok markus
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/ipsec_input.c49
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