Properly preserve ip_tos bits for IPv4 packets

Restructure code slightly to save ip_tos bits earlier.  Fix the bug
where the ip_tos field is zeroed out before assigning to the iptos
variable. Restore the ip_tos and ip_ver fields only if they have
been zeroed during the pseudo-header checksum calculation.

Reviewed by:	cem, gnn, hiren
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D8053
This commit is contained in:
Kurt Lidl 2016-09-29 19:45:24 +00:00
parent b5663de9eb
commit 1d7ee746e6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=306458

View File

@ -603,7 +603,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
#ifdef TCP_SIGNATURE
uint8_t sig_checked = 0;
#endif
uint8_t iptos = 0;
uint8_t iptos;
struct m_tag *fwd_tag = NULL;
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
@ -675,6 +675,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
/* XXX stat */
goto drop;
}
iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
}
#endif
#if defined(INET) && defined(INET6)
@ -701,6 +702,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
th = (struct tcphdr *)((caddr_t)ip + off0);
tlen = ntohs(ip->ip_len) - off0;
iptos = ip->ip_tos;
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;
@ -721,29 +723,20 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
ipov->ih_len = htons(tlen);
th->th_sum = in_cksum(m, len);
/* Reset length for SDT probes. */
ip->ip_len = htons(tlen + off0);
ip->ip_len = htons(len);
/* Reset TOS bits */
ip->ip_tos = iptos;
/* Re-initialization for later version check */
ip->ip_v = IPVERSION;
}
if (th->th_sum) {
TCPSTAT_INC(tcps_rcvbadsum);
goto drop;
}
/* Re-initialization for later version check */
ip->ip_v = IPVERSION;
}
#endif /* INET */
#ifdef INET6
if (isipv6)
iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
#endif
#if defined(INET) && defined(INET6)
else
#endif
#ifdef INET
iptos = ip->ip_tos;
#endif
/*
* Check that TCP offset makes sense,
* pull out TCP options and adjust length. XXX