diff --git a/client/streamconfigdialog.cpp b/client/streamconfigdialog.cpp
index 913e773..e04983e 100644
--- a/client/streamconfigdialog.cpp
+++ b/client/streamconfigdialog.cpp
@@ -113,6 +113,15 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
if (validProtocolCount == 0)
connect(btn1, SIGNAL(clicked(bool)),
bgProto[i+1]->button(ButtonIdNone), SLOT(click()));
+
+ // If the id1 protocol doesn't have a payload (e.g. IGMP)
+ // force payload protocol to 'None'
+ if (!OstProtocolManager->protocolHasPayload(id1))
+ {
+ connect(btn1, SIGNAL(clicked(bool)),
+ bgProto[ProtoPayload]->button(ButtonIdNone),
+ SLOT(click()));
+ }
}
}
}
diff --git a/common/abstractprotocol.cpp b/common/abstractprotocol.cpp
index 5462b19..ef80783 100644
--- a/common/abstractprotocol.cpp
+++ b/common/abstractprotocol.cpp
@@ -79,6 +79,7 @@ AbstractProtocol::AbstractProtocol(StreamBase *stream, AbstractProtocol *parent)
_metaFieldCount = -1;
_frameFieldCount = -1;
protoSize = -1;
+ _hasPayload = true;
}
/*!
@@ -614,6 +615,18 @@ bool AbstractProtocol::isProtocolFramePayloadSizeVariable() const
return false;
}
+/*!
+ Returns true if the protocol typically contains a payload or other protocols
+ following it e.g. TCP, UDP have payloads, while ARP, IGMP do not
+
+ The default implementation returns true. If a subclass does not have a
+ payload, it should set the _hasPayload data member to false
+*/
+bool AbstractProtocol::protocolHasPayload() const
+{
+ return _hasPayload;
+}
+
/*!
Returns the checksum (of the requested type) of the protocol's contents
diff --git a/common/abstractprotocol.h b/common/abstractprotocol.h
index 053e303..07350cc 100644
--- a/common/abstractprotocol.h
+++ b/common/abstractprotocol.h
@@ -59,6 +59,9 @@ protected:
AbstractProtocol *prev; //!< Protocol preceding this protocol
AbstractProtocol *next; //!< Protocol succeeding this protocol
+ //! Is protocol typically followed by payload or another protocol
+ bool _hasPayload;
+
public:
//! Properties of a field, can be OR'd
enum FieldFlag {
@@ -139,6 +142,8 @@ public:
bool isProtocolFramePayloadValueVariable() const;
bool isProtocolFramePayloadSizeVariable() const;
+ bool protocolHasPayload() const;
+
virtual quint32 protocolFrameCksum(int streamIndex = 0,
CksumType cksumType = CksumIp) const;
quint32 protocolFrameHeaderCksum(int streamIndex = 0,
diff --git a/common/arp.cpp b/common/arp.cpp
index 844a2d7..f23b6b6 100644
--- a/common/arp.cpp
+++ b/common/arp.cpp
@@ -88,6 +88,7 @@ void ArpConfigForm::on_targetProtoAddrMode_currentIndexChanged(int index)
ArpProtocol::ArpProtocol(StreamBase *stream, AbstractProtocol *parent)
: AbstractProtocol(stream, parent)
{
+ _hasPayload = false;
configForm = NULL;
}
diff --git a/common/gmp.cpp b/common/gmp.cpp
index f477a4e..7bfb938 100755
--- a/common/gmp.cpp
+++ b/common/gmp.cpp
@@ -29,16 +29,6 @@ GmpConfigForm::GmpConfigForm(QWidget *parent)
{
setupUi(this);
- // TODO: this should be in subclass
- msgTypeCombo->setValueMask(0xFF);
- msgTypeCombo->addItem(kIgmpV1Query, "IGMPv1 Query");
- msgTypeCombo->addItem(kIgmpV1Report, "IGMPv1 Report");
- msgTypeCombo->addItem(kIgmpV2Query, "IGMPv2 Query");
- msgTypeCombo->addItem(kIgmpV2Report, "IGMPv2 Report");
- msgTypeCombo->addItem(kIgmpV2Leave, "IGMPv2 Leave");
- msgTypeCombo->addItem(kIgmpV3Query, "IGMPv3 Query");
- msgTypeCombo->addItem(kIgmpV3Report, "IGMPv3 Report");
-
auxData->setValidator(new QRegExpValidator(
QRegExp("[0-9A-Fa-f]*"), this));
}
@@ -54,43 +44,6 @@ void GmpConfigForm::update()
groupList->currentItem());
}
-void GmpConfigForm::on_msgTypeCombo_currentIndexChanged(int /*index*/)
-{
- switch(msgTypeCombo->currentValue())
- {
- case kIgmpV1Query:
- case kIgmpV1Report:
- case kIgmpV2Query:
- case kIgmpV2Report:
- case kIgmpV2Leave:
- case kMldV1Query:
- case kMldV1Report:
- case kMldV1Done:
- asmGroup->show();
- ssmWidget->hide();
- break;
-
- case kIgmpV3Query:
- case kMldV2Query:
- asmGroup->hide();
- ssmWidget->setCurrentIndex(kSsmQueryPage);
- ssmWidget->show();
- break;
-
- case kIgmpV3Report:
- case kMldV2Report:
- asmGroup->hide();
- ssmWidget->setCurrentIndex(kSsmReportPage);
- ssmWidget->show();
- break;
-
- default:
- asmGroup->hide();
- ssmWidget->hide();
- break;
- }
-}
-
void GmpConfigForm::on_groupMode_currentIndexChanged(int index)
{
bool disabled = (index == 0);
diff --git a/common/gmp.h b/common/gmp.h
index f2af688..97dc5fd 100755
--- a/common/gmp.h
+++ b/common/gmp.h
@@ -27,31 +27,6 @@ along with this program. If not, see
#include
-// Both IGMP and MLD use the same msg type value for 'Query' message
-// across versions despite the fields being different. To distinguish
-// Query messages of different versions, we use an additional upper byte
-enum GmpMsgType
-{
- // IGMP
- kIgmpV1Query = 0x11,
- kIgmpV1Report = 0x12,
-
- kIgmpV2Query = 0xFF11,
- kIgmpV2Report = 0x16,
- kIgmpV2Leave = 0x17,
-
- kIgmpV3Query = 0xFE11,
- kIgmpV3Report = 0x22,
-
- // MLD
- kMldV1Query = 0x82,
- kMldV1Report = 0x83,
- kMldV1Done = 0x84,
-
- kMldV2Query = 0xFF82,
- kMldV2Report = 0x8F
-};
-
/*
Gmp Protocol Frame Format - TODO: for now see the respective RFCs
*/
@@ -67,13 +42,11 @@ public:
protected:
QString _defaultGroupIp;
QString _defaultSourceIp;
-private:
enum {
kSsmQueryPage = 0,
kSsmReportPage = 1
};
private slots:
- void on_msgTypeCombo_currentIndexChanged(int index);
void on_groupMode_currentIndexChanged(int index);
void on_addSource_clicked();
void on_deleteSource_clicked();
@@ -163,11 +136,11 @@ protected:
OstProto::Gmp data;
GmpConfigForm *configForm;
- GmpMsgType msgType() const;
+ int msgType() const;
- virtual bool isSsmReport() const;
- virtual bool isQuery() const;
- virtual bool isSsmQuery() const;
+ virtual bool isSsmReport() const = 0;
+ virtual bool isQuery() const = 0;
+ virtual bool isSsmQuery() const = 0;
int qqic(int value) const;
@@ -176,30 +149,9 @@ private:
static QHash frameFieldCountMap;
};
-inline GmpMsgType GmpProtocol::msgType() const
+inline int GmpProtocol::msgType() const
{
- return GmpMsgType(fieldData(kType, FieldValue).toUInt());
-}
-
-inline bool GmpProtocol::isSsmReport() const
-{
- return ((msgType() == kIgmpV3Report)
- || (msgType() == kMldV2Report ));
-}
-
-inline bool GmpProtocol::isQuery() const
-{
- return ((msgType() == kIgmpV1Query)
- || (msgType() == kIgmpV2Query)
- || (msgType() == kIgmpV3Query)
- || (msgType() == kMldV1Query )
- || (msgType() == kMldV2Query ));
-}
-
-inline bool GmpProtocol::isSsmQuery() const
-{
- return ((msgType() == kIgmpV3Query)
- || (msgType() == kMldV2Query ));
+ return fieldData(kType, FieldValue).toInt();
}
inline int GmpProtocol::qqic(int value) const
diff --git a/common/igmp.cpp b/common/igmp.cpp
index de8d06f..046f675 100644
--- a/common/igmp.cpp
+++ b/common/igmp.cpp
@@ -28,6 +28,18 @@ along with this program. If not, see
IgmpConfigForm::IgmpConfigForm(QWidget *parent)
: GmpConfigForm(parent)
{
+ connect(msgTypeCombo, SIGNAL(currentIndexChanged(int)),
+ SLOT(on_msgTypeCombo_currentIndexChanged(int)));
+
+ msgTypeCombo->setValueMask(0xFF);
+ msgTypeCombo->addItem(kIgmpV1Query, "IGMPv1 Query");
+ msgTypeCombo->addItem(kIgmpV1Report, "IGMPv1 Report");
+ msgTypeCombo->addItem(kIgmpV2Query, "IGMPv2 Query");
+ msgTypeCombo->addItem(kIgmpV2Report, "IGMPv2 Report");
+ msgTypeCombo->addItem(kIgmpV2Leave, "IGMPv2 Leave");
+ msgTypeCombo->addItem(kIgmpV3Query, "IGMPv3 Query");
+ msgTypeCombo->addItem(kIgmpV3Report, "IGMPv3 Report");
+
_defaultGroupIp = "0.0.0.0";
_defaultSourceIp = "0.0.0.0";
@@ -37,9 +49,43 @@ IgmpConfigForm::IgmpConfigForm(QWidget *parent)
groupRecordSourceList->setItemDelegate(new IPv4AddressDelegate(this));
}
+void IgmpConfigForm::on_msgTypeCombo_currentIndexChanged(int /*index*/)
+{
+ switch(msgTypeCombo->currentValue())
+ {
+ case kIgmpV1Query:
+ case kIgmpV1Report:
+ case kIgmpV2Query:
+ case kIgmpV2Report:
+ case kIgmpV2Leave:
+ asmGroup->show();
+ ssmWidget->hide();
+ break;
+
+ case kIgmpV3Query:
+ asmGroup->hide();
+ ssmWidget->setCurrentIndex(kSsmQueryPage);
+ ssmWidget->show();
+ break;
+
+ case kIgmpV3Report:
+ asmGroup->hide();
+ ssmWidget->setCurrentIndex(kSsmReportPage);
+ ssmWidget->show();
+ break;
+
+ default:
+ asmGroup->hide();
+ ssmWidget->hide();
+ break;
+ }
+}
+
IgmpProtocol::IgmpProtocol(StreamBase *stream, AbstractProtocol *parent)
: GmpProtocol(stream, parent)
{
+ _hasPayload = false;
+
data.set_type(kIgmpV2Query);
}
@@ -388,7 +434,7 @@ quint16 IgmpProtocol::checksum(int streamIndex) const
{
quint16 cks;
quint32 sum = 0;
-#if 1 // FIXME
+
// TODO: add as a new CksumType (CksumIgmp?) and implement in AbsProto
cks = protocolFrameCksum(streamIndex, CksumIp);
sum += (quint16) ~cks;
@@ -398,6 +444,6 @@ quint16 IgmpProtocol::checksum(int streamIndex) const
sum = (sum & 0xFFFF) + (sum >> 16);
cks = (~sum) & 0xFFFF;
-#endif
+
return cks;
}
diff --git a/common/igmp.h b/common/igmp.h
index a140a70..a5d50d4 100644
--- a/common/igmp.h
+++ b/common/igmp.h
@@ -22,11 +22,30 @@ along with this program. If not, see
#include "igmp.pb.h"
#include "gmp.h"
+// IGMP uses the same msg type value for 'Query' messages across
+// versions despite the fields being different. To distinguish
+// Query messages of different versions, we use an additional
+// upper byte
+enum IgmpMsgType
+{
+ kIgmpV1Query = 0x11,
+ kIgmpV1Report = 0x12,
+
+ kIgmpV2Query = 0xFF11,
+ kIgmpV2Report = 0x16,
+ kIgmpV2Leave = 0x17,
+
+ kIgmpV3Query = 0xFE11,
+ kIgmpV3Report = 0x22,
+};
+
class IgmpConfigForm : public GmpConfigForm
{
+ Q_OBJECT
public:
IgmpConfigForm(QWidget *parent = 0);
private slots:
+ void on_msgTypeCombo_currentIndexChanged(int index);
};
class IgmpProtocol : public GmpProtocol
@@ -57,11 +76,32 @@ public:
virtual void storeConfigWidget();
protected:
+ virtual bool isSsmReport() const;
+ virtual bool isQuery() const;
+ virtual bool isSsmQuery() const;
+
virtual quint16 checksum(int streamIndex) const;
private:
int mrc(int value) const;
};
+inline bool IgmpProtocol::isSsmReport() const
+{
+ return (msgType() == kIgmpV3Report);
+}
+
+inline bool IgmpProtocol::isQuery() const
+{
+ return ((msgType() == kIgmpV1Query)
+ || (msgType() == kIgmpV2Query)
+ || (msgType() == kIgmpV3Query));
+}
+
+inline bool IgmpProtocol::isSsmQuery() const
+{
+ return (msgType() == kIgmpV3Query);
+}
+
inline int IgmpProtocol::mrc(int value) const
{
return quint8(value); // TODO: if value > 128, convert to mantissa/exp form
diff --git a/common/mld.cpp b/common/mld.cpp
index 2f50535..7caf77a 100644
--- a/common/mld.cpp
+++ b/common/mld.cpp
@@ -49,11 +49,44 @@ public:
MldConfigForm::MldConfigForm(QWidget *parent)
: GmpConfigForm(parent)
{
+ connect(msgTypeCombo, SIGNAL(currentIndexChanged(int)),
+ SLOT(on_msgTypeCombo_currentIndexChanged(int)));
+
_defaultSourceIp = "::";
sourceList->setItemDelegate(new IpAddressDelegate(this));
groupRecordSourceList->setItemDelegate(new IpAddressDelegate(this));
}
+void MldConfigForm::on_msgTypeCombo_currentIndexChanged(int /*index*/)
+{
+ switch(msgTypeCombo->currentValue())
+ {
+ case kMldV1Query:
+ case kMldV1Report:
+ case kMldV1Done:
+ asmGroup->show();
+ ssmWidget->hide();
+ break;
+
+ case kMldV2Query:
+ asmGroup->hide();
+ ssmWidget->setCurrentIndex(kSsmQueryPage);
+ ssmWidget->show();
+ break;
+
+ case kMldV2Report:
+ asmGroup->hide();
+ ssmWidget->setCurrentIndex(kSsmReportPage);
+ ssmWidget->show();
+ break;
+
+ default:
+ asmGroup->hide();
+ ssmWidget->hide();
+ break;
+ }
+}
+
MldProtocol::MldProtocol(StreamBase *stream, AbstractProtocol *parent)
: GmpProtocol(stream, parent)
{
diff --git a/common/mld.h b/common/mld.h
index 0d087c9..a66965f 100644
--- a/common/mld.h
+++ b/common/mld.h
@@ -25,11 +25,27 @@ along with this program. If not, see
#include "abstractprotocol.h"
+// MLD uses the same msg type value for 'Query' messages across
+// versions despite the fields being different. To distinguish
+// Query messages of different versions, we use an additional
+// upper byte
+enum MldMsgType
+{
+ kMldV1Query = 0x82,
+ kMldV1Report = 0x83,
+ kMldV1Done = 0x84,
+
+ kMldV2Query = 0xFF82,
+ kMldV2Report = 0x8F
+};
+
class MldConfigForm : public GmpConfigForm
{
+ Q_OBJECT
public:
MldConfigForm(QWidget *parent = 0);
private slots:
+ void on_msgTypeCombo_currentIndexChanged(int index);
};
class MldProtocol : public GmpProtocol
@@ -60,7 +76,28 @@ public:
virtual void loadConfigWidget();
virtual void storeConfigWidget();
protected:
+ virtual bool isSsmReport() const;
+ virtual bool isQuery() const;
+ virtual bool isSsmQuery() const;
+
virtual quint16 checksum(int streamIndex) const;
};
+inline bool MldProtocol::isSsmReport() const
+{
+ return (msgType() == kMldV2Report);
+}
+
+inline bool MldProtocol::isQuery() const
+{
+ return ((msgType() == kMldV1Query)
+ || (msgType() == kMldV2Query));
+}
+
+inline bool MldProtocol::isSsmQuery() const
+{
+ return (msgType() == kMldV2Query);
+}
+
+
#endif
diff --git a/common/protocolmanager.cpp b/common/protocolmanager.cpp
index abcc518..24f5e87 100644
--- a/common/protocolmanager.cpp
+++ b/common/protocolmanager.cpp
@@ -122,8 +122,9 @@ ProtocolManager::~ProtocolManager()
nameToNumberMap.clear();
neighbourProtocols.clear();
factory.clear();
- while (!protocolList.isEmpty())
- delete protocolList.takeFirst();
+ QList pl = protocolList.values();
+ while (!pl.isEmpty())
+ delete pl.takeFirst();
}
void ProtocolManager::registerProtocol(int protoNumber,
@@ -136,7 +137,7 @@ void ProtocolManager::registerProtocol(int protoNumber,
factory.insert(protoNumber, protoInstanceCreator);
p = createProtocol(protoNumber, NULL);
- protocolList.append(p);
+ protocolList.insert(protoNumber, p);
numberToNameMap.insert(protoNumber, p->shortName());
nameToNumberMap.insert(p->shortName(), protoNumber);
@@ -190,6 +191,13 @@ bool ProtocolManager::isValidNeighbour(int protoPrefix, int protoSuffix)
return false;
}
+bool ProtocolManager::protocolHasPayload(int protoNumber)
+{
+ Q_ASSERT(protocolList.contains(protoNumber));
+
+ return protocolList.value(protoNumber)->protocolHasPayload();
+}
+
QStringList ProtocolManager::protocolDatabase()
{
return numberToNameMap.values();
diff --git a/common/protocolmanager.h b/common/protocolmanager.h
index ac64919..77ea81c 100644
--- a/common/protocolmanager.h
+++ b/common/protocolmanager.h
@@ -32,7 +32,7 @@ class ProtocolManager
QMap nameToNumberMap;
QMultiMap neighbourProtocols;
QMap factory;
- QList protocolList;
+ QMap protocolList;
void populateNeighbourProtocols();
@@ -48,6 +48,7 @@ public:
AbstractProtocol *parent = 0);
bool isValidNeighbour(int protoPrefix, int protoSuffix);
+ bool protocolHasPayload(int protoNumber);
QStringList protocolDatabase();
};
diff --git a/common/streambase.cpp b/common/streambase.cpp
index 6ba1909..f766fd7 100644
--- a/common/streambase.cpp
+++ b/common/streambase.cpp
@@ -444,6 +444,10 @@ int StreamBase::frameValue(uchar *buf, int bufMaxSize, int frameIndex) const
}
delete iter;
+ // Pad with zero, if required
+ if (len < pktLen)
+ memset(buf+len, 0, pktLen-len);
+
return pktLen;
}