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
|
to prevent infinite recursion
|
||||||
*/
|
*/
|
||||||
quint32 AbstractProtocol::protocolFrameCksum(int streamIndex,
|
quint32 AbstractProtocol::protocolFrameCksum(int streamIndex,
|
||||||
CksumType cksumType) const
|
CksumType cksumType, CksumFlags cksumFlags) const
|
||||||
{
|
{
|
||||||
static int recursionCount = 0;
|
static int recursionCount = 0;
|
||||||
quint32 cksum = 0xFFFFFFFF;
|
quint32 cksum = 0xFFFFFFFF;
|
||||||
@ -865,8 +865,10 @@ quint32 AbstractProtocol::protocolFrameCksum(int streamIndex,
|
|||||||
QByteArray fv;
|
QByteArray fv;
|
||||||
quint16 *ip;
|
quint16 *ip;
|
||||||
quint32 len, sum = 0;
|
quint32 len, sum = 0;
|
||||||
|
bool forCksum = cksumFlags.testFlag(IncludeCksumField) ?
|
||||||
|
false : true;
|
||||||
|
|
||||||
fv = protocolFrameValue(streamIndex, true);
|
fv = protocolFrameValue(streamIndex, forCksum);
|
||||||
ip = (quint16*) fv.constData();
|
ip = (quint16*) fv.constData();
|
||||||
len = fv.size();
|
len = fv.size();
|
||||||
|
|
||||||
@ -994,7 +996,7 @@ quint32 AbstractProtocol::protocolFramePayloadCksum(int streamIndex,
|
|||||||
if (!p)
|
if (!p)
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
|
|
||||||
cksum = p->protocolFrameCksum(streamIndex, cksumType);
|
cksum = p->protocolFrameCksum(streamIndex, cksumType, IncludeCksumField);
|
||||||
sum = (quint16) ~cksum;
|
sum = (quint16) ~cksum;
|
||||||
if (cksumScope == CksumScopeAdjacentProtocol)
|
if (cksumScope == CksumScopeAdjacentProtocol)
|
||||||
goto out;
|
goto out;
|
||||||
@ -1002,9 +1004,9 @@ quint32 AbstractProtocol::protocolFramePayloadCksum(int streamIndex,
|
|||||||
p = p->next;
|
p = p->next;
|
||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
|
cksum = p->protocolFrameCksum(streamIndex, cksumType, IncludeCksumField);
|
||||||
// when combining cksums, a non-first protocol starting at odd offset
|
// when combining cksums, a non-first protocol starting at odd offset
|
||||||
// needs a byte swap (see RFC 1071 section(s) 2A, 2B)
|
// needs a byte swap (see RFC 1071 section(s) 2A, 2B)
|
||||||
cksum = p->protocolFrameCksum(streamIndex, cksumType);
|
|
||||||
if (p->protocolFrameOffset(streamIndex) & 0x1)
|
if (p->protocolFrameOffset(streamIndex) & 0x1)
|
||||||
cksum = swap16(cksum);
|
cksum = swap16(cksum);
|
||||||
sum += (quint16) ~cksum;
|
sum += (quint16) ~cksum;
|
||||||
|
@ -106,6 +106,12 @@ public:
|
|||||||
CksumMax //!< Marker for number of cksum types
|
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
|
//! Supported checksum scopes
|
||||||
enum CksumScope {
|
enum CksumScope {
|
||||||
CksumScopeAdjacentProtocol, //!< Cksum only the adjacent protocol
|
CksumScopeAdjacentProtocol, //!< Cksum only the adjacent protocol
|
||||||
@ -164,7 +170,7 @@ public:
|
|||||||
bool protocolHasPayload() const;
|
bool protocolHasPayload() const;
|
||||||
|
|
||||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||||
CksumType cksumType = CksumIp) const;
|
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||||
quint32 protocolFrameHeaderCksum(int streamIndex = 0,
|
quint32 protocolFrameHeaderCksum(int streamIndex = 0,
|
||||||
CksumType cksumType = CksumIp,
|
CksumType cksumType = CksumIp,
|
||||||
CksumScope cksumScope = CksumScopeAdjacentProtocol) const;
|
CksumScope cksumScope = CksumScopeAdjacentProtocol) const;
|
||||||
|
@ -168,14 +168,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
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
|
// For a Pseudo IP cksum, we assume it is the succeeding protocol
|
||||||
// that is requesting it and hence return protoB's cksum;
|
// that is requesting it and hence return protoB's cksum;
|
||||||
if (cksumType == CksumIpPseudo)
|
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
|
#if 0
|
||||||
quint32 protocolFrameHeaderCksum(int streamIndex = 0,
|
quint32 protocolFrameHeaderCksum(int streamIndex = 0,
|
||||||
|
@ -845,7 +845,7 @@ int Ip4Protocol::protocolFrameVariableCount() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
quint32 Ip4Protocol::protocolFrameCksum(int streamIndex,
|
quint32 Ip4Protocol::protocolFrameCksum(int streamIndex,
|
||||||
CksumType cksumType) const
|
CksumType cksumType, CksumFlags cksumFlags) const
|
||||||
{
|
{
|
||||||
switch (cksumType)
|
switch (cksumType)
|
||||||
{
|
{
|
||||||
@ -876,7 +876,8 @@ quint32 Ip4Protocol::protocolFrameCksum(int streamIndex,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
return AbstractProtocol::protocolFrameCksum(
|
||||||
|
streamIndex, cksumType, cksumFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ip4Protocol::hasErrors(QStringList *errors) const
|
bool Ip4Protocol::hasErrors(QStringList *errors) const
|
||||||
|
@ -89,7 +89,7 @@ public:
|
|||||||
virtual int protocolFrameVariableCount() const;
|
virtual int protocolFrameVariableCount() const;
|
||||||
|
|
||||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||||
CksumType cksumType = CksumIp) const;
|
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||||
|
|
||||||
virtual bool hasErrors(QStringList *errors = nullptr) const;
|
virtual bool hasErrors(QStringList *errors = nullptr) const;
|
||||||
private:
|
private:
|
||||||
|
@ -740,7 +740,7 @@ int Ip6Protocol::protocolFrameVariableCount() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
quint32 Ip6Protocol::protocolFrameCksum(int streamIndex,
|
quint32 Ip6Protocol::protocolFrameCksum(int streamIndex,
|
||||||
CksumType cksumType) const
|
CksumType cksumType, CksumFlags cksumFlags) const
|
||||||
{
|
{
|
||||||
if (cksumType == CksumIpPseudo)
|
if (cksumType == CksumIpPseudo)
|
||||||
{
|
{
|
||||||
@ -764,7 +764,8 @@ quint32 Ip6Protocol::protocolFrameCksum(int streamIndex,
|
|||||||
|
|
||||||
return qFromBigEndian((quint16) ~sum);
|
return qFromBigEndian((quint16) ~sum);
|
||||||
}
|
}
|
||||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
return AbstractProtocol::protocolFrameCksum(
|
||||||
|
streamIndex, cksumType, cksumFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ip6Protocol::hasErrors(QStringList *errors) const
|
bool Ip6Protocol::hasErrors(QStringList *errors) const
|
||||||
|
@ -103,7 +103,7 @@ public:
|
|||||||
virtual int protocolFrameVariableCount() const;
|
virtual int protocolFrameVariableCount() const;
|
||||||
|
|
||||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||||
CksumType cksumType = CksumIp) const;
|
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||||
|
|
||||||
virtual bool hasErrors(QStringList *errors = nullptr) const;
|
virtual bool hasErrors(QStringList *errors = nullptr) const;
|
||||||
private:
|
private:
|
||||||
|
@ -225,7 +225,7 @@ int UserScriptProtocol::protocolFrameVariableCount() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
quint32 UserScriptProtocol::protocolFrameCksum(int streamIndex,
|
quint32 UserScriptProtocol::protocolFrameCksum(int streamIndex,
|
||||||
CksumType cksumType) const
|
CksumType cksumType, CksumFlags cksumFlags) const
|
||||||
{
|
{
|
||||||
QScriptValue userFunction;
|
QScriptValue userFunction;
|
||||||
QScriptValue userValue;
|
QScriptValue userValue;
|
||||||
@ -243,9 +243,12 @@ quint32 UserScriptProtocol::protocolFrameCksum(int streamIndex,
|
|||||||
|
|
||||||
Q_ASSERT(userFunction.isFunction());
|
Q_ASSERT(userFunction.isFunction());
|
||||||
|
|
||||||
userValue = userFunction.call(QScriptValue(),
|
userValue = userFunction.call(
|
||||||
QScriptValueList() << QScriptValue(&engine_, streamIndex)
|
QScriptValue(),
|
||||||
<< QScriptValue(&engine_, cksumType));
|
QScriptValueList()
|
||||||
|
<< QScriptValue(&engine_, streamIndex)
|
||||||
|
<< QScriptValue(&engine_, cksumType)
|
||||||
|
<< QScriptValue(&engine_, cksumFlags));
|
||||||
|
|
||||||
Q_ASSERT(userValue.isValid());
|
Q_ASSERT(userValue.isValid());
|
||||||
Q_ASSERT(userValue.isNumber());
|
Q_ASSERT(userValue.isNumber());
|
||||||
@ -253,7 +256,8 @@ quint32 UserScriptProtocol::protocolFrameCksum(int streamIndex,
|
|||||||
return userValue.toUInt32();
|
return userValue.toUInt32();
|
||||||
|
|
||||||
_do_default:
|
_do_default:
|
||||||
return AbstractProtocol::protocolFrameCksum(streamIndex, cksumType);
|
return AbstractProtocol::protocolFrameCksum(
|
||||||
|
streamIndex, cksumType, cksumFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserScriptProtocol::evaluateUserScript() const
|
void UserScriptProtocol::evaluateUserScript() const
|
||||||
|
@ -58,6 +58,13 @@ public:
|
|||||||
CksumTcpUdp = AbstractProtocol::CksumTcpUdp
|
CksumTcpUdp = AbstractProtocol::CksumTcpUdp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CksumFlag
|
||||||
|
{
|
||||||
|
IncludeCksumField = AbstractProtocol::IncludeCksumField
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(CksumFlags, CksumFlag);
|
||||||
|
Q_FLAG(CksumFlags);
|
||||||
|
|
||||||
UserProtocol(AbstractProtocol *parent);
|
UserProtocol(AbstractProtocol *parent);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@ -131,7 +138,7 @@ public:
|
|||||||
virtual int protocolFrameVariableCount() const;
|
virtual int protocolFrameVariableCount() const;
|
||||||
|
|
||||||
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
virtual quint32 protocolFrameCksum(int streamIndex = 0,
|
||||||
CksumType cksumType = CksumIp) const;
|
CksumType cksumType = CksumIp, CksumFlags cksumFlags = 0) const;
|
||||||
|
|
||||||
void evaluateUserScript() const;
|
void evaluateUserScript() const;
|
||||||
bool isScriptValid() const;
|
bool isScriptValid() const;
|
||||||
|
Loading…
Reference in New Issue
Block a user