Fix incorrect UDP/ICMP checksums
For UDP encaps like VxLAN or Geneve, which can contain IP as payload, the UDP checksum was incorrect because when summing UDP payload (i.e. IP), we skipped the IPv4 checksum field, which should not be skipped in this case. Similar issue, for ICMP with IP as payload, ICMP checksum was incorrect. Essentially, any protocol which checksums over its payload and the payload contains protocols with checksum fields.
This commit is contained in:
parent
96b6424cae
commit
a498dbf21a
@ -850,7 +850,7 @@ bool AbstractProtocol::protocolHasPayload() const
|
||||
to prevent infinite recursion
|
||||
*/
|
||||
quint32 AbstractProtocol::protocolFrameCksum(int streamIndex,
|
||||
CksumType cksumType) const
|
||||
CksumType cksumType, CksumFlags cksumFlags) const
|
||||
{
|
||||
static int recursionCount = 0;
|
||||
quint32 cksum = 0xFFFFFFFF;
|
||||
@ -865,8 +865,10 @@ quint32 AbstractProtocol::protocolFrameCksum(int streamIndex,
|
||||
QByteArray fv;
|
||||
quint16 *ip;
|
||||
quint32 len, sum = 0;
|
||||
bool forCksum = cksumFlags.testFlag(IncludeCksumField) ?
|
||||
false : true;
|
||||
|
||||
fv = protocolFrameValue(streamIndex, true);
|
||||
fv = protocolFrameValue(streamIndex, forCksum);
|
||||
ip = (quint16*) fv.constData();
|
||||
len = fv.size();
|
||||
|
||||
@ -994,7 +996,7 @@ quint32 AbstractProtocol::protocolFramePayloadCksum(int streamIndex,
|
||||
if (!p)
|
||||
return 0xFFFF;
|
||||
|
||||
cksum = p->protocolFrameCksum(streamIndex, cksumType);
|
||||
cksum = p->protocolFrameCksum(streamIndex, cksumType, IncludeCksumField);
|
||||
sum = (quint16) ~cksum;
|
||||
if (cksumScope == CksumScopeAdjacentProtocol)
|
||||
goto out;
|
||||
@ -1002,9 +1004,9 @@ quint32 AbstractProtocol::protocolFramePayloadCksum(int streamIndex,
|
||||
p = p->next;
|
||||
while (p)
|
||||
{
|
||||
cksum = p->protocolFrameCksum(streamIndex, cksumType, IncludeCksumField);
|
||||
// when combining cksums, a non-first protocol starting at odd offset
|
||||
// needs a byte swap (see RFC 1071 section(s) 2A, 2B)
|
||||
cksum = p->protocolFrameCksum(streamIndex, cksumType);
|
||||
if (p->protocolFrameOffset(streamIndex) & 0x1)
|
||||
cksum = swap16(cksum);
|
||||
sum += (quint16) ~cksum;
|
||||
|
@ -106,6 +106,12 @@ public:
|
||||
CksumMax //!< Marker for number of cksum types
|
||||
};
|
||||
|
||||
//! Flags affecting cksum calculation, can be OR'd
|
||||
enum CksumFlag {
|
||||
IncludeCksumField = 0x1, //!< Default: exclude cksum field(s)
|
||||
};
|
||||
Q_DECLARE_FLAGS(CksumFlags, CksumFlag); //!< \private abcd
|
||||
|
||||
//! Supported checksum scopes
|
||||
enum CksumScope {
|
||||
CksumScopeAdjacentProtocol, //!< Cksum only the adjacent protocol
|
||||
@ -164,7 +170,7 @@ public:
|
||||
bool protocolHasPayload() const;
|
||||
|
||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||
CksumType cksumType = CksumIp) const;
|
||||
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||
quint32 protocolFrameHeaderCksum(int streamIndex = 0,
|
||||
CksumType cksumType = CksumIp,
|
||||
CksumScope cksumScope = CksumScopeAdjacentProtocol) const;
|
||||
|
@ -168,14 +168,16 @@ public:
|
||||
}
|
||||
|
||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||
CksumType cksumType = CksumIp) const
|
||||
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const
|
||||
{
|
||||
// For a Pseudo IP cksum, we assume it is the succeeding protocol
|
||||
// that is requesting it and hence return protoB's cksum;
|
||||
if (cksumType == CksumIpPseudo)
|
||||
return protoB->protocolFrameCksum(streamIndex, cksumType);
|
||||
return protoB->protocolFrameCksum(
|
||||
streamIndex,cksumType, cksumFlags);
|
||||
|
||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
||||
return AbstractProtocol::protocolFrameCksum(
|
||||
streamIndex, cksumType, cksumFlags);
|
||||
}
|
||||
#if 0
|
||||
quint32 protocolFrameHeaderCksum(int streamIndex = 0,
|
||||
|
@ -845,7 +845,7 @@ int Ip4Protocol::protocolFrameVariableCount() const
|
||||
}
|
||||
|
||||
quint32 Ip4Protocol::protocolFrameCksum(int streamIndex,
|
||||
CksumType cksumType) const
|
||||
CksumType cksumType, CksumFlags cksumFlags) const
|
||||
{
|
||||
switch (cksumType)
|
||||
{
|
||||
@ -876,7 +876,8 @@ quint32 Ip4Protocol::protocolFrameCksum(int streamIndex,
|
||||
break;
|
||||
}
|
||||
|
||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
||||
return AbstractProtocol::protocolFrameCksum(
|
||||
streamIndex, cksumType, cksumFlags);
|
||||
}
|
||||
|
||||
bool Ip4Protocol::hasErrors(QStringList *errors) const
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
virtual int protocolFrameVariableCount() const;
|
||||
|
||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||
CksumType cksumType = CksumIp) const;
|
||||
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||
|
||||
virtual bool hasErrors(QStringList *errors = nullptr) const;
|
||||
private:
|
||||
|
@ -740,7 +740,7 @@ int Ip6Protocol::protocolFrameVariableCount() const
|
||||
}
|
||||
|
||||
quint32 Ip6Protocol::protocolFrameCksum(int streamIndex,
|
||||
CksumType cksumType) const
|
||||
CksumType cksumType, CksumFlags cksumFlags) const
|
||||
{
|
||||
if (cksumType == CksumIpPseudo)
|
||||
{
|
||||
@ -764,7 +764,8 @@ quint32 Ip6Protocol::protocolFrameCksum(int streamIndex,
|
||||
|
||||
return qFromBigEndian((quint16) ~sum);
|
||||
}
|
||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
||||
return AbstractProtocol::protocolFrameCksum(
|
||||
streamIndex, cksumType, cksumFlags);
|
||||
}
|
||||
|
||||
bool Ip6Protocol::hasErrors(QStringList *errors) const
|
||||
|
@ -103,7 +103,7 @@ public:
|
||||
virtual int protocolFrameVariableCount() const;
|
||||
|
||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||
CksumType cksumType = CksumIp) const;
|
||||
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||
|
||||
virtual bool hasErrors(QStringList *errors = nullptr) const;
|
||||
private:
|
||||
|
@ -225,7 +225,7 @@ int UserScriptProtocol::protocolFrameVariableCount() const
|
||||
}
|
||||
|
||||
quint32 UserScriptProtocol::protocolFrameCksum(int streamIndex,
|
||||
CksumType cksumType) const
|
||||
CksumType cksumType, CksumFlags cksumFlags) const
|
||||
{
|
||||
QScriptValue userFunction;
|
||||
QScriptValue userValue;
|
||||
@ -243,9 +243,12 @@ quint32 UserScriptProtocol::protocolFrameCksum(int streamIndex,
|
||||
|
||||
Q_ASSERT(userFunction.isFunction());
|
||||
|
||||
userValue = userFunction.call(QScriptValue(),
|
||||
QScriptValueList() << QScriptValue(&engine_, streamIndex)
|
||||
<< QScriptValue(&engine_, cksumType));
|
||||
userValue = userFunction.call(
|
||||
QScriptValue(),
|
||||
QScriptValueList()
|
||||
<< QScriptValue(&engine_, streamIndex)
|
||||
<< QScriptValue(&engine_, cksumType)
|
||||
<< QScriptValue(&engine_, cksumFlags));
|
||||
|
||||
Q_ASSERT(userValue.isValid());
|
||||
Q_ASSERT(userValue.isNumber());
|
||||
@ -253,7 +256,8 @@ quint32 UserScriptProtocol::protocolFrameCksum(int streamIndex,
|
||||
return userValue.toUInt32();
|
||||
|
||||
_do_default:
|
||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
||||
return AbstractProtocol::protocolFrameCksum(
|
||||
streamIndex, cksumType, cksumFlags);
|
||||
}
|
||||
|
||||
void UserScriptProtocol::evaluateUserScript() const
|
||||
|
@ -58,6 +58,13 @@ public:
|
||||
CksumTcpUdp = AbstractProtocol::CksumTcpUdp
|
||||
};
|
||||
|
||||
enum CksumFlag
|
||||
{
|
||||
IncludeCksumField = AbstractProtocol::IncludeCksumField
|
||||
};
|
||||
Q_DECLARE_FLAGS(CksumFlags, CksumFlag);
|
||||
Q_FLAG(CksumFlags);
|
||||
|
||||
UserProtocol(AbstractProtocol *parent);
|
||||
|
||||
public slots:
|
||||
@ -131,7 +138,7 @@ public:
|
||||
virtual int protocolFrameVariableCount() const;
|
||||
|
||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||
CksumType cksumType = CksumIp) const;
|
||||
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||
|
||||
void evaluateUserScript() const;
|
||||
bool isScriptValid() const;
|
||||
|
Loading…
Reference in New Issue
Block a user