Bugfix: Fix incorrect cksums
Presence of IPv6 Extension Headers was causing incorrect TCP/UDP/ICMP cksums. Verified that with these changes, cksums are correct for all combinations of L3 and L4 headers with/without options/extHdrs Fixes #271
This commit is contained in:
parent
4924d7fe60
commit
488a2ea730
@ -930,18 +930,27 @@ quint32 AbstractProtocol::protocolFrameHeaderCksum(int streamIndex,
|
|||||||
CksumType cksumType, CksumScope cksumScope) const
|
CksumType cksumType, CksumScope cksumScope) const
|
||||||
{
|
{
|
||||||
quint32 sum = 0;
|
quint32 sum = 0;
|
||||||
quint16 cksum;
|
quint32 cksum;
|
||||||
AbstractProtocol *p = prev;
|
AbstractProtocol *p = prev;
|
||||||
|
|
||||||
Q_ASSERT(cksumType == CksumIpPseudo);
|
Q_ASSERT(cksumType == CksumIpPseudo);
|
||||||
|
|
||||||
|
// We may have extension headers between us and the IP header - skip 'em
|
||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
cksum = p->protocolFrameCksum(streamIndex, cksumType);
|
cksum = p->protocolFrameCksum(streamIndex, cksumType);
|
||||||
|
if (cksum <= 0xFFFF) // protocol has a valid pseudo cksum ie its IP
|
||||||
|
{
|
||||||
sum += (quint16) ~cksum;
|
sum += (quint16) ~cksum;
|
||||||
qDebug("%s: sum = %u, cksum = %u", __FUNCTION__, sum, cksum);
|
// Ip4/6Protocol::protocolFrameCksum(CksumIpPseudo) only
|
||||||
|
// counts the src/dst IP (see Note in there)
|
||||||
|
// Count the payload length and protocolId here
|
||||||
|
sum += protocolFrameSize() + protocolFramePayloadSize();
|
||||||
|
sum += protocolId(ProtocolIdIp);
|
||||||
|
qDebug("%s: sum = %x, cksum = %x", __FUNCTION__, sum, cksum);
|
||||||
if (cksumScope == CksumScopeAdjacentProtocol)
|
if (cksumScope == CksumScopeAdjacentProtocol)
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
p = p->prev;
|
p = p->prev;
|
||||||
}
|
}
|
||||||
if (parent)
|
if (parent)
|
||||||
|
@ -859,14 +859,18 @@ quint32 Ip4Protocol::protocolFrameCksum(int streamIndex,
|
|||||||
sum += *((quint16*)(p + 14)); // src-ip lo
|
sum += *((quint16*)(p + 14)); // src-ip lo
|
||||||
sum += *((quint16*)(p + 16)); // dst-ip hi
|
sum += *((quint16*)(p + 16)); // dst-ip hi
|
||||||
sum += *((quint16*)(p + 18)); // dst-ip lo
|
sum += *((quint16*)(p + 18)); // dst-ip lo
|
||||||
sum += qToBigEndian((quint16)
|
|
||||||
protocolFramePayloadSize(streamIndex)); // len
|
// XXX: payload length and protocol are also part of the
|
||||||
sum += qToBigEndian((quint16) *(p + 9)); // proto
|
// pseudo cksum but for IPv6 we need to skip extension headers to
|
||||||
|
// get to them, so these two fields are counted in the
|
||||||
|
// pseudo cksum in AbstractProtocol::protocolFrameHeaderCksum()
|
||||||
|
// Although not needed for IPv4 case, we do the same for IPv4
|
||||||
|
// also, so that code there is common for IPv4 and IPv6
|
||||||
|
|
||||||
while(sum>>16)
|
while(sum>>16)
|
||||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
|
|
||||||
return ~qFromBigEndian((quint16)sum);
|
return qFromBigEndian((quint16) ~sum);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -781,13 +781,18 @@ quint32 Ip6Protocol::protocolFrameCksum(int streamIndex,
|
|||||||
// src-ip, dst-ip
|
// src-ip, dst-ip
|
||||||
for (int i = 8; i < fv.size(); i+=2)
|
for (int i = 8; i < fv.size(); i+=2)
|
||||||
sum += *((quint16*)(p + i));
|
sum += *((quint16*)(p + i));
|
||||||
sum += *((quint16*)(p + 4)); // payload len
|
|
||||||
sum += qToBigEndian((quint16) *(p + 6)); // proto
|
// XXX: payload length and protocol are also part of the
|
||||||
|
// pseudo cksum but we need to skip extension headers to
|
||||||
|
// get to them as per RFC 8200 Section 8.1
|
||||||
|
// Since we can't traverse beyond our immediate neighboring
|
||||||
|
// protocol from here, these two fields are counted in the
|
||||||
|
// pseudo cksum in AbstractProtocol::protocolFrameHeaderCksum()
|
||||||
|
|
||||||
while(sum>>16)
|
while(sum>>16)
|
||||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
|
|
||||||
return ~qFromBigEndian((quint16)sum);
|
return qFromBigEndian((quint16) ~sum);
|
||||||
}
|
}
|
||||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user