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() {