summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 1d2d8c3..dc8ba3c 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -100,6 +100,8 @@ struct tcphdr tcp_savetcp;
#include <netkey/key.h>
#endif /*IPSEC*/
+#include <machine/in_cksum.h>
+
MALLOC_DEFINE(M_TSEGQ, "tseg_qent", "TCP segment queue entry");
static int tcprexmtthresh = 3;
@@ -425,17 +427,27 @@ tcp_input(m, off0, proto)
}
ip = mtod(m, struct ip *);
ipov = (struct ipovly *)ip;
-
- /*
- * Checksum extended TCP header and data.
- */
- tlen = ip->ip_len;
- len = sizeof (struct ip) + tlen;
- bzero(ipov->ih_x1, sizeof(ipov->ih_x1));
- ipov->ih_len = (u_short)tlen;
- HTONS(ipov->ih_len);
th = (struct tcphdr *)((caddr_t)ip + off0);
- th->th_sum = in_cksum(m, len);
+ tlen = ip->ip_len;
+
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+ if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
+ th->th_sum = m->m_pkthdr.csum_data;
+ else
+ th->th_sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr, htonl(m->m_pkthdr.csum_data +
+ ip->ip_len + IPPROTO_TCP));
+ th->th_sum ^= 0xffff;
+ } else {
+ /*
+ * Checksum extended TCP header and data.
+ */
+ len = sizeof (struct ip) + tlen;
+ bzero(ipov->ih_x1, sizeof(ipov->ih_x1));
+ ipov->ih_len = (u_short)tlen;
+ HTONS(ipov->ih_len);
+ th->th_sum = in_cksum(m, len);
+ }
if (th->th_sum) {
tcpstat.tcps_rcvbadsum++;
goto drop;
OpenPOWER on IntegriCloud