diff --git a/client/fieldedit.cpp b/client/fieldedit.cpp
index 2c0ea0e..835bfc5 100644
--- a/client/fieldedit.cpp
+++ b/client/fieldedit.cpp
@@ -46,6 +46,7 @@ void FieldEdit::setType(FieldType type)
break;
case kIp6Address:
setValidator(&ip6Validator_);
+ setPlaceholderText("::");
break;
default:
setValidator(nullptr);
diff --git a/client/findreplace.cpp b/client/findreplace.cpp
index 582852e..accab25 100644
--- a/client/findreplace.cpp
+++ b/client/findreplace.cpp
@@ -19,9 +19,11 @@ along with this program. If not, see
#include "findreplace.h"
-#include "../common/abstractprotocol.h"
-#include "../common/protocolmanager.h"
+#include "abstractprotocol.h"
+#include "iputils.h"
+#include "protocolmanager.h"
#include "stream.h"
+#include "uint128.h"
#include
@@ -103,6 +105,12 @@ void FindReplaceDialog::on_field_currentIndexChanged(int index)
QRegularExpression::CaseInsensitiveOption)))) {
findValue->setType(FieldEdit::kIp4Address);
replaceValue->setType(FieldEdit::kIp4Address);
+ } else if ((fieldAttrib.bitSize == 128)
+ && (fieldName.contains(QRegularExpression(
+ "address|source|destination",
+ QRegularExpression::CaseInsensitiveOption)))) {
+ findValue->setType(FieldEdit::kIp6Address);
+ replaceValue->setType(FieldEdit::kIp6Address);
} else {
qDebug("XXXXXX %s bitSize %d max %llx",
qPrintable(field->currentText()),
@@ -123,30 +131,52 @@ void FindReplaceDialog::on_buttonBox_accepted()
action_->fieldIndex = fieldAttrib.index;
action_->fieldBitSize = fieldAttrib.bitSize;
+ // TODO: Change <= 64 to uint64 instead of string
// XXX: All find/replace value/mask QVariants are set to
// 64-bit decimal number encoded as string
// - The action user is expected to convert to appropriate type
// (fieldBitSize is included as a hint)
// - QVariant can only do decimal conversions (not hex)
- if (matchAny->isChecked()) {
- action_->findMask.setValue(QString("0"));
- action_->findValue.setValue(QString("0"));
- } else {
- action_->findMask.setValue(QString::number(
- useFindMask->isChecked() ?
- findMask->text().toULongLong(nullptr, BASE_HEX) :
- quint64(~0)));
- action_->findValue.setValue(QString::number(
- findValue->text().toULongLong(nullptr, 0)));
- }
+ if (fieldAttrib.bitSize == 128) { // IPv6 address
+ if (matchAny->isChecked()) {
+ action_->findMask.setValue(UInt128(0));
+ action_->findValue.setValue(UInt128(0));
+ } else {
+ action_->findMask.setValue(
+ useFindMask->isChecked() ?
+ ipUtils::ip6StringToUInt128(findMask->text()) :
+ ~UInt128(0));
+ action_->findValue.setValue(
+ ipUtils::ip6StringToUInt128(findValue->text()));
+ }
- action_->replaceMask.setValue(QString::number(
- useReplaceMask->isChecked() ?
- replaceMask->text().toULongLong(nullptr, BASE_HEX) :
- quint64(~0)));
- action_->replaceValue.setValue(QString::number(
- replaceValue->text().toULongLong(nullptr, 0)));
+ action_->replaceMask.setValue(
+ useReplaceMask->isChecked() ?
+ ipUtils::ip6StringToUInt128(replaceMask->text()) :
+ ~UInt128(0));
+ action_->replaceValue.setValue(
+ ipUtils::ip6StringToUInt128(replaceValue->text()));
+ } else { // everything else
+ if (matchAny->isChecked()) {
+ action_->findMask.setValue(QString("0"));
+ action_->findValue.setValue(QString("0"));
+ } else {
+ action_->findMask.setValue(QString::number(
+ useFindMask->isChecked() ?
+ findMask->text().toULongLong(nullptr, BASE_HEX) :
+ quint64(~0)));
+ action_->findValue.setValue(QString::number(
+ findValue->text().toULongLong(nullptr, 0)));
+ }
+
+ action_->replaceMask.setValue(QString::number(
+ useReplaceMask->isChecked() ?
+ replaceMask->text().toULongLong(nullptr, BASE_HEX) :
+ quint64(~0)));
+ action_->replaceValue.setValue(QString::number(
+ replaceValue->text().toULongLong(nullptr, 0)));
+ }
action_->selectedStreamsOnly = selectedStreamsOnly->isChecked();
}
diff --git a/common/ip6.cpp b/common/ip6.cpp
index 398f354..e7417d2 100644
--- a/common/ip6.cpp
+++ b/common/ip6.cpp
@@ -354,6 +354,11 @@ QVariant Ip6Protocol::fieldData(int index, FieldAttrib attrib,
case FieldName:
return QString("Source");
case FieldValue:
+ {
+ QVariant v;
+ v.setValue(src);
+ return v;
+ }
case FieldFrameValue:
case FieldTextValue:
{
@@ -412,6 +417,11 @@ QVariant Ip6Protocol::fieldData(int index, FieldAttrib attrib,
case FieldName:
return QString("Destination");
case FieldValue:
+ {
+ QVariant v;
+ v.setValue(dst);
+ return v;
+ }
case FieldFrameValue:
case FieldTextValue:
{
@@ -594,6 +604,14 @@ bool Ip6Protocol::setFieldData(int index, const QVariant &value,
}
case ip6_srcAddress:
{
+ if (value.typeName() == QString("UInt128")) {
+ UInt128 addr = value.value();
+ data.set_src_addr_hi(addr.hi64());
+ data.set_src_addr_lo(addr.lo64());
+ isOk = true;
+ break;
+ }
+
Q_IPV6ADDR addr = QHostAddress(value.toString()).toIPv6Address();
quint64 x;
@@ -620,6 +638,14 @@ bool Ip6Protocol::setFieldData(int index, const QVariant &value,
}
case ip6_dstAddress:
{
+ if (value.typeName() == QString("UInt128")) {
+ UInt128 addr = value.value();
+ data.set_dst_addr_hi(addr.hi64());
+ data.set_dst_addr_lo(addr.lo64());
+ isOk = true;
+ break;
+ }
+
Q_IPV6ADDR addr = QHostAddress(value.toString()).toIPv6Address();
quint64 x;
diff --git a/common/iputils.h b/common/iputils.h
index 0d6a067..51d2f5b 100644
--- a/common/iputils.h
+++ b/common/iputils.h
@@ -20,6 +20,10 @@ along with this program. If not, see
#ifndef _IP_UTILS_H
#define _IP_UTILS_H
+#include "uint128.h"
+
+#include
+
namespace ipUtils {
enum AddrMode {
kFixed = 0,
@@ -118,5 +122,31 @@ void inline ipAddress(quint64 baseIpHi, quint64 baseIpLo, int prefix,
}
}
+UInt128 inline ip6StringToUInt128(QString ip6Str)
+{
+ Q_IPV6ADDR addr = QHostAddress(ip6Str).toIPv6Address();
+ quint64 hi, lo;
+
+ hi = (quint64(addr[0]) << 56)
+ | (quint64(addr[1]) << 48)
+ | (quint64(addr[2]) << 40)
+ | (quint64(addr[3]) << 32)
+ | (quint64(addr[4]) << 24)
+ | (quint64(addr[5]) << 16)
+ | (quint64(addr[6]) << 8)
+ | (quint64(addr[7]) << 0);
+
+ lo = (quint64(addr[ 8]) << 56)
+ | (quint64(addr[ 9]) << 48)
+ | (quint64(addr[10]) << 40)
+ | (quint64(addr[11]) << 32)
+ | (quint64(addr[12]) << 24)
+ | (quint64(addr[13]) << 16)
+ | (quint64(addr[14]) << 8)
+ | (quint64(addr[15]) << 0);
+
+ return UInt128(hi, lo);
+}
+
} // namespace ipUtils
#endif
diff --git a/common/streambase.cpp b/common/streambase.cpp
index 006e0e7..510c3b2 100644
--- a/common/streambase.cpp
+++ b/common/streambase.cpp
@@ -18,11 +18,13 @@ along with this program. If not, see
*/
#include "streambase.h"
+
#include "abstractprotocol.h"
#include "framevalueattrib.h"
#include "protocollist.h"
#include "protocollistiterator.h"
#include "protocolmanager.h"
+#include "uint128.h"
#include
@@ -628,7 +630,10 @@ int StreamBase::findReplace(quint32 protocolNumber, int fieldIndex,
<< "replaceMask" << hex << replaceMask.value() << dec
<< "replaceValue" << replaceValue.value()
<< "newValue" << newValue;
- if (proto->setFieldData(fieldIndex, newValue))
+
+ QVariant nv;
+ nv.setValue(newValue);
+ if (proto->setFieldData(fieldIndex, nv))
replaceCount++;
}
}
@@ -646,7 +651,9 @@ int StreamBase::protocolFieldReplace(quint32 protocolNumber,
return findReplace(protocolNumber, fieldIndex,
findValue, findMask, replaceValue, replaceMask);
- // TODO: > 64 (e.g. IPv6 128 bit)
+ if (fieldBitSize == 128)
+ return findReplace(protocolNumber, fieldIndex,
+ findValue, findMask, replaceValue, replaceMask);
qWarning("Unknown find/replace type %d", findValue.type());
return 0;
diff --git a/common/uint128.h b/common/uint128.h
index f03fe06..68f4f57 100644
--- a/common/uint128.h
+++ b/common/uint128.h
@@ -54,6 +54,7 @@ private:
quint64 lo_;
quint8 array_[16];
};
+Q_DECLARE_METATYPE(UInt128);
inline UInt128::UInt128()
{