diff --git a/common/ip6.cpp b/common/ip6.cpp
index 172eb74..62ebdb7 100644
--- a/common/ip6.cpp
+++ b/common/ip6.cpp
@@ -18,6 +18,8 @@ along with this program. If not, see
*/
#include "ip6.h"
+
+#include "uint128.h"
#include
@@ -313,49 +315,34 @@ QVariant Ip6Protocol::fieldData(int index, FieldAttrib attrib,
case ip6_srcAddress:
{
- int u, p, q;
- quint64 maskHi = 0, maskLo = 0;
- quint64 prefixHi, prefixLo;
- quint64 hostHi = 0, hostLo = 0;
- quint64 srcHi = 0, srcLo = 0;
+ int u;
+ UInt128 mask = 0;
+ UInt128 prefix = 0;
+ UInt128 host = 0;
+ UInt128 src(data.src_addr_hi(), data.src_addr_lo());
switch(data.src_addr_mode())
{
case OstProto::Ip6::kFixed:
- srcHi = data.src_addr_hi();
- srcLo = data.src_addr_lo();
break;
case OstProto::Ip6::kIncHost:
case OstProto::Ip6::kDecHost:
case OstProto::Ip6::kRandomHost:
u = streamIndex % data.src_addr_count();
- if (data.src_addr_prefix() > 64) {
- p = 64;
- q = data.src_addr_prefix() - 64;
- } else {
- p = data.src_addr_prefix();
- q = 0;
- }
- if (p > 0)
- maskHi = ~((quint64(1) << p) - 1);
- if (q > 0)
- maskLo = ~((quint64(1) << q) - 1);
- prefixHi = data.src_addr_hi() & maskHi;
- prefixLo = data.src_addr_lo() & maskLo;
+ mask = ~UInt128(0, 0) << (128 - data.src_addr_prefix());
+ prefix = src & mask;
if (data.src_addr_mode() == OstProto::Ip6::kIncHost) {
- hostHi = ((data.src_addr_hi() & ~maskHi) + u) & ~maskHi;
- hostLo = ((data.src_addr_lo() & ~maskLo) + u) & ~maskLo;
+ host = ((src & ~mask) + u) & ~mask;
}
else if (data.src_addr_mode() == OstProto::Ip6::kDecHost) {
- hostHi = ((data.src_addr_hi() & ~maskHi) - u) & ~maskHi;
- hostLo = ((data.src_addr_lo() & ~maskLo) - u) & ~maskLo;
+ host = ((src & ~mask) - u) & ~mask;
}
else if (data.src_addr_mode()==OstProto::Ip6::kRandomHost) {
- hostHi = qrand() & ~maskHi;
- hostLo = qrand() & ~maskLo;
+ // XXX: qrand is int (32bit) not 64bit, some stdlib
+ // implementations have RAND_MAX as low as 0x7FFF
+ host = UInt128(qrand(), qrand()) & ~mask;
}
- srcHi = prefixHi | hostHi;
- srcLo = prefixLo | hostLo;
+ src = prefix | host;
break;
default:
qWarning("Unhandled src_addr_mode = %d",
@@ -372,10 +359,9 @@ QVariant Ip6Protocol::fieldData(int index, FieldAttrib attrib,
{
QByteArray fv;
fv.resize(16);
- qToBigEndian(srcHi, (uchar*) fv.data());
- qToBigEndian(srcLo, (uchar*) (fv.data() + 8));
+ qToBigEndian(src, (uchar*) fv.data());
if (attrib == FieldTextValue)
- return QHostAddress((quint8*)fv.constData()).toString();
+ return QHostAddress(src.toArray()).toString();
else
return fv;
}
@@ -387,49 +373,34 @@ QVariant Ip6Protocol::fieldData(int index, FieldAttrib attrib,
case ip6_dstAddress:
{
- int u, p, q;
- quint64 maskHi = 0, maskLo = 0;
- quint64 prefixHi, prefixLo;
- quint64 hostHi = 0, hostLo = 0;
- quint64 dstHi = 0, dstLo = 0;
+ int u;
+ UInt128 mask = 0;
+ UInt128 prefix = 0;
+ UInt128 host = 0;
+ UInt128 dst(data.dst_addr_hi(), data.dst_addr_lo());
switch(data.dst_addr_mode())
{
case OstProto::Ip6::kFixed:
- dstHi = data.dst_addr_hi();
- dstLo = data.dst_addr_lo();
break;
case OstProto::Ip6::kIncHost:
case OstProto::Ip6::kDecHost:
case OstProto::Ip6::kRandomHost:
u = streamIndex % data.dst_addr_count();
- if (data.dst_addr_prefix() > 64) {
- p = 64;
- q = data.dst_addr_prefix() - 64;
- } else {
- p = data.dst_addr_prefix();
- q = 0;
- }
- if (p > 0)
- maskHi = ~((quint64(1) << p) - 1);
- if (q > 0)
- maskLo = ~((quint64(1) << q) - 1);
- prefixHi = data.dst_addr_hi() & maskHi;
- prefixLo = data.dst_addr_lo() & maskLo;
+ mask = ~UInt128(0, 0) << (128 - data.dst_addr_prefix());
+ prefix = dst & mask;
if (data.dst_addr_mode() == OstProto::Ip6::kIncHost) {
- hostHi = ((data.dst_addr_hi() & ~maskHi) + u) & ~maskHi;
- hostLo = ((data.dst_addr_lo() & ~maskLo) + u) & ~maskLo;
+ host = ((dst & ~mask) + u) & ~mask;
}
else if (data.dst_addr_mode() == OstProto::Ip6::kDecHost) {
- hostHi = ((data.dst_addr_hi() & ~maskHi) - u) & ~maskHi;
- hostLo = ((data.dst_addr_lo() & ~maskLo) - u) & ~maskLo;
+ host = ((dst & ~mask) - u) & ~mask;
}
else if (data.dst_addr_mode()==OstProto::Ip6::kRandomHost) {
- hostHi = qrand() & ~maskHi;
- hostLo = qrand() & ~maskLo;
+ // XXX: qrand is int (32bit) not 64bit, some stdlib
+ // implementations have RAND_MAX as low as 0x7FFF
+ host = UInt128(qrand(), qrand()) & ~mask;
}
- dstHi = prefixHi | hostHi;
- dstLo = prefixLo | hostLo;
+ dst = prefix | host;
break;
default:
qWarning("Unhandled dst_addr_mode = %d",
@@ -446,10 +417,9 @@ QVariant Ip6Protocol::fieldData(int index, FieldAttrib attrib,
{
QByteArray fv;
fv.resize(16);
- qToBigEndian(dstHi, (uchar*) fv.data());
- qToBigEndian(dstLo, (uchar*) (fv.data() + 8));
+ qToBigEndian(dst, (uchar*) fv.data());
if (attrib == FieldTextValue)
- return QHostAddress((quint8*)fv.constData()).toString();
+ return QHostAddress(dst.toArray()).toString();
else
return fv;
}
diff --git a/common/uint128.h b/common/uint128.h
index 8d1fc46..f03fe06 100644
--- a/common/uint128.h
+++ b/common/uint128.h
@@ -22,6 +22,7 @@ along with this program. If not, see
#include
+#include
#include
#include
@@ -41,6 +42,7 @@ public:
bool operator==(const UInt128 &other) const;
bool operator!=(const UInt128 &other) const;
UInt128 operator+(const UInt128 &other) const;
+ UInt128 operator-(const UInt128 &other) const;
UInt128 operator*(const uint &other) const;
UInt128 operator<<(const int &shift) const;
UInt128 operator~() const;
@@ -134,6 +136,16 @@ inline UInt128 UInt128::operator+(const UInt128 &other) const
return sum;
}
+inline UInt128 UInt128::operator-(const UInt128 &other) const
+{
+ UInt128 diff;
+
+ diff.lo_ = lo_ - other.lo_;
+ diff.hi_ = hi_ - other.hi_ - (diff.lo_ > lo_);
+
+ return diff;
+}
+
inline UInt128 UInt128::operator*(const uint &other) const
{
UInt128 product;
@@ -184,6 +196,15 @@ template <> inline UInt128 qFromBigEndian(const uchar *src)
return UInt128(hi, lo);
}
+#if QT_VERSION >= 0x050700
+template <> inline void qToBigEndian(UInt128 src, void *dest)
+#else
+template <> inline void qToBigEndian(UInt128 src, uchar *dest)
+#endif
+{
+ memcpy(dest, src.toArray(), 16);
+}
+
template <> inline UInt128 qToBigEndian(const UInt128 src)
{
quint64 hi, lo;
@@ -194,6 +215,14 @@ template <> inline UInt128 qToBigEndian(const UInt128 src)
return UInt128(hi, lo);
}
+inline QDebug operator<<(QDebug debug, const UInt128 &value)
+{
+ QDebugStateSaver saver(debug);
+ debug.maybeSpace() << hex << value.hi64() << " " << value.lo64();
+
+ return debug;
+}
+
inline uint qHash(const UInt128 &key)
{
return qHash(key.hi64()) ^ qHash(key.lo64());