Extended ICMP to work for ICMPv6 as well as ICMPv4

This commit is contained in:
Srivats P. 2010-06-11 20:48:24 +05:30
parent 069cc16279
commit fedc4ec5d1
4 changed files with 249 additions and 73 deletions

View File

@ -23,45 +23,86 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include <QSet>
#include <qendian.h>
const int kIcmpEchoReply = 0;
const int kIcmpDestinationUnreachable = 3;
const int kIcmpSourceQuench = 4;
const int kIcmpRedirect = 5;
const int kIcmpEchoRequest = 8;
const int kIcmpTimeExceeded = 11;
const int kIcmpParameterProblem = 12;
const int kIcmpTimestampRequest = 13;
const int kIcmpTimestampReply = 14;
const int kIcmpInformationRequest = 15;
const int kIcmpInformationReply = 16;
const int kIcmpAddressMaskRequest = 17;
const int kIcmpAddressMaskReply = 18;
enum IcmpType
{
kIcmpEchoReply = 0,
kIcmpDestinationUnreachable = 3,
kIcmpSourceQuench = 4,
kIcmpRedirect = 5,
kIcmpEchoRequest = 8,
kIcmpTimeExceeded = 11,
kIcmpParameterProblem = 12,
kIcmpTimestampRequest = 13,
kIcmpTimestampReply = 14,
kIcmpInformationRequest = 15,
kIcmpInformationReply = 16,
kIcmpAddressMaskRequest = 17,
kIcmpAddressMaskReply = 18
};
static QSet<int> idSeqSet = QSet<int>()
enum Icmp6Type
{
kIcmp6DestinationUnreachable = 1,
kIcmp6PacketTooBig = 2,
kIcmp6TimeExceeded = 3,
kIcmp6ParameterProblem = 4,
kIcmp6EchoRequest = 128,
kIcmp6EchoReply = 129,
kIcmp6RouterSolicitation = 133,
kIcmp6RouterAdvertisement = 134,
kIcmp6NeighbourSolicitation = 135,
kIcmp6NeighbourAdvertisement = 136,
kIcmp6Redirect = 137,
kIcmp6InformationQuery = 139,
kIcmp6InformationResponse = 140
};
static QSet<int> icmpIdSeqSet = QSet<int>()
<< kIcmpEchoRequest
<< kIcmpEchoReply
<< kIcmpInformationRequest
<< kIcmpInformationReply;
static QSet<int> icmp6IdSeqSet = QSet<int>()
<< kIcmp6EchoRequest
<< kIcmp6EchoReply;
static bool isIdSeqType(OstProto::Icmp::Version ver, int type)
{
//qDebug("%s: ver = %d, type = %d", __FUNCTION__, ver, type);
switch(ver)
{
case OstProto::Icmp::kIcmp4:
return icmpIdSeqSet.contains(type);
case OstProto::Icmp::kIcmp6:
return icmp6IdSeqSet.contains(type);
default:
break;
}
Q_ASSERT(false); // unreachable
return false;
}
IcmpConfigForm::IcmpConfigForm(QWidget *parent)
: QWidget(parent)
{
versionGroup = new QButtonGroup(this);
setupUi(this);
// auto-connect's not working, for some reason I can't figure out!
// slot name changed to when_ instead of on_ so that connectSlotsByName()
// doesn't complain
connect(versionGroup,
SIGNAL(buttonClicked(int)),
SLOT(when_versionGroup_buttonClicked(int)));
versionGroup->addButton(icmp4Button, OstProto::Icmp::kIcmp4);
versionGroup->addButton(icmp6Button, OstProto::Icmp::kIcmp6);
typeCombo->setValidator(new QIntValidator(0, 0xFF, this));
typeCombo->addItem(kIcmpEchoReply, "Echo Reply");
typeCombo->addItem(kIcmpDestinationUnreachable, "Destination Unreachable");
typeCombo->addItem(kIcmpSourceQuench, "Source Quench");
typeCombo->addItem(kIcmpRedirect, "Redirect");
typeCombo->addItem(kIcmpEchoRequest, "Echo Request");
typeCombo->addItem(kIcmpTimeExceeded, "Time Exceeded");
typeCombo->addItem(kIcmpParameterProblem, "Parameter Problem");
typeCombo->addItem(kIcmpTimestampRequest, "Timestamp Request");
typeCombo->addItem(kIcmpTimestampReply, "Timestamp Reply");
typeCombo->addItem(kIcmpInformationRequest, "Information Request");
typeCombo->addItem(kIcmpInformationReply, "Information Reply");
typeCombo->addItem(kIcmpAddressMaskRequest, "Address Mask Request");
typeCombo->addItem(kIcmpAddressMaskReply, "Address Mask Reply");
icmp4Button->click();
idEdit->setValidator(new QIntValidator(0, 0xFFFF, this));
seqEdit->setValidator(new QIntValidator(0, 0xFFFF, this));
@ -69,7 +110,61 @@ IcmpConfigForm::IcmpConfigForm(QWidget *parent)
void IcmpConfigForm::on_typeCombo_currentIndexChanged(int /*index*/)
{
idSeqFrame->setVisible(idSeqSet.contains(typeCombo->currentValue()));
idSeqFrame->setVisible(
isIdSeqType(
OstProto::Icmp::Version(versionGroup->checkedId()),
typeCombo->currentValue()));
}
void IcmpConfigForm::when_versionGroup_buttonClicked(int id)
{
int value = typeCombo->currentValue();
typeCombo->clear();
switch(id)
{
case OstProto::Icmp::kIcmp4:
typeCombo->addItem(kIcmpEchoReply, "Echo Reply");
typeCombo->addItem(kIcmpDestinationUnreachable,
"Destination Unreachable");
typeCombo->addItem(kIcmpSourceQuench, "Source Quench");
typeCombo->addItem(kIcmpRedirect, "Redirect");
typeCombo->addItem(kIcmpEchoRequest, "Echo Request");
typeCombo->addItem(kIcmpTimeExceeded, "Time Exceeded");
typeCombo->addItem(kIcmpParameterProblem, "Parameter Problem");
typeCombo->addItem(kIcmpTimestampRequest, "Timestamp Request");
typeCombo->addItem(kIcmpTimestampReply, "Timestamp Reply");
typeCombo->addItem(kIcmpInformationRequest, "Information Request");
typeCombo->addItem(kIcmpInformationReply, "Information Reply");
typeCombo->addItem(kIcmpAddressMaskRequest, "Address Mask Request");
typeCombo->addItem(kIcmpAddressMaskReply, "Address Mask Reply");
break;
case OstProto::Icmp::kIcmp6:
typeCombo->addItem(kIcmp6DestinationUnreachable,
"Destination Unreachable");
typeCombo->addItem(kIcmp6PacketTooBig, "Packet Too Big");
typeCombo->addItem(kIcmp6TimeExceeded, "Time Exceeded");
typeCombo->addItem(kIcmp6ParameterProblem, "Parameter Problem");
typeCombo->addItem(kIcmp6EchoRequest, "Echo Request");
typeCombo->addItem(kIcmp6EchoReply, "Echo Reply");
typeCombo->addItem(kIcmp6RouterSolicitation, "Router Solicitation");
typeCombo->addItem(kIcmp6RouterAdvertisement, "Router Advertisement");
typeCombo->addItem(kIcmp6NeighbourSolicitation,
"Neighbour Solicitation");
typeCombo->addItem(kIcmp6NeighbourAdvertisement,
"Neighbour Advertisement");
typeCombo->addItem(kIcmp6Redirect, "Redirect");
typeCombo->addItem(kIcmp6InformationQuery, "Information Query");
typeCombo->addItem(kIcmp6InformationResponse, "Information Response");
break;
default:
Q_ASSERT(false);
}
typeCombo->setValue(value);
}
IcmpProtocol::IcmpProtocol(StreamBase *stream, AbstractProtocol *parent)
@ -121,7 +216,13 @@ quint32 IcmpProtocol::protocolId(ProtocolIdType type) const
{
switch(type)
{
case ProtocolIdIp: return 0x1;
case ProtocolIdIp:
switch(icmpVersion())
{
case OstProto::Icmp::kIcmp4: return 0x1;
case OstProto::Icmp::kIcmp6: return 0x3A;
default:break;
}
default:break;
}
@ -137,7 +238,7 @@ int IcmpProtocol::frameFieldCount() const
{
int count;
if (idSeqSet.contains(fieldData(icmp_type, FieldValue).toUInt()))
if (isIdSeqType(icmpVersion(), icmpType()))
count = icmp_idSeqFrameFieldCount;
else
count = icmp_commonFrameFieldCount;
@ -164,10 +265,11 @@ AbstractProtocol::FieldFlags IcmpProtocol::fieldFlags(int index) const
case icmp_identifier:
case icmp_sequence:
if (!idSeqSet.contains(fieldData(icmp_type, FieldValue).toUInt()))
if (!isIdSeqType(icmpVersion(), icmpType()))
flags &= ~FrameField;
break;
case icmp_version:
case icmp_is_override_checksum:
flags &= ~FrameField;
flags |= MetaField;
@ -249,6 +351,12 @@ QVariant IcmpProtocol::fieldData(int index, FieldAttrib attrib,
sum += (quint16) ~cks;
cks = protocolFramePayloadCksum(streamIndex, CksumIp);
sum += (quint16) ~cks;
if (icmpVersion() == OstProto::Icmp::kIcmp6)
{
cks = protocolFrameHeaderCksum(streamIndex,
CksumIpPseudo);
sum += (quint16) ~cks;
}
while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);
@ -333,6 +441,17 @@ QVariant IcmpProtocol::fieldData(int index, FieldAttrib attrib,
// Meta fields
case icmp_version:
{
switch(attrib)
{
case FieldValue:
return data.icmp_version();
default:
break;
}
break;
}
case icmp_is_override_checksum:
{
switch(attrib)
@ -398,6 +517,13 @@ bool IcmpProtocol::setFieldData(int index, const QVariant &value,
data.set_sequence(seq);
break;
}
case icmp_version:
{
int ver = value.toUInt(&isOk);
if (isOk)
data.set_icmp_version(OstProto::Icmp::Version(ver));
break;
}
case icmp_is_override_checksum:
{
bool ovr = value.toBool();
@ -430,6 +556,8 @@ void IcmpProtocol::loadConfigWidget()
{
configWidget();
configForm->versionGroup->button(icmpVersion())->click();
configForm->typeCombo->setValue(fieldData(icmp_type, FieldValue).toUInt());
configForm->codeEdit->setText(fieldData(icmp_code, FieldValue).toString());
@ -450,6 +578,9 @@ void IcmpProtocol::storeConfigWidget()
bool isOk;
configWidget();
setFieldData(icmp_version, configForm->versionGroup->checkedId());
setFieldData(icmp_type, configForm->typeCombo->currentValue());
setFieldData(icmp_code, configForm->codeEdit->text());

View File

@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "abstractprotocol.h"
#include <QButtonGroup>
/*
Icmp Protocol Frame Format -
+-----+------+------+------+-------+
@ -39,9 +41,12 @@ class IcmpConfigForm : public QWidget, public Ui::Icmp
{
Q_OBJECT
public:
QButtonGroup *versionGroup;
IcmpConfigForm(QWidget *parent = 0);
private slots:
void on_typeCombo_currentIndexChanged(int index);
void when_versionGroup_buttonClicked(int id);
};
class IcmpProtocol : public AbstractProtocol
@ -63,10 +68,22 @@ private:
// Meta Fields
icmp_is_override_checksum = icmp_idSeqFrameFieldCount,
icmp_version,
icmp_fieldCount
};
OstProto::Icmp::Version icmpVersion() const
{
return OstProto::Icmp::Version(
fieldData(icmp_version, FieldValue).toUInt());
}
int icmpType() const
{
return fieldData(icmp_type, FieldValue).toInt();
}
public:
IcmpProtocol(StreamBase *stream, AbstractProtocol *parent = 0);
virtual ~IcmpProtocol();

View File

@ -24,13 +24,19 @@ package OstProto;
// Icmp Protocol
message Icmp {
optional bool is_override_checksum = 1;
enum Version {
kIcmp4 = 4;
kIcmp6 = 6;
}
optional uint32 type = 2 [default = 0x8]; // echo request
optional uint32 code = 3;
optional uint32 checksum = 4;
optional uint32 identifier = 5 [default = 1234];
optional uint32 sequence = 6;
optional Version icmp_version = 1 [default = kIcmp4];
optional bool is_override_checksum = 2;
optional uint32 type = 6 [default = 0x8]; // echo request
optional uint32 code = 7;
optional uint32 checksum = 8;
optional uint32 identifier = 9 [default = 1234];
optional uint32 sequence = 10;
}
extend Protocol {

View File

@ -5,15 +5,38 @@
<rect>
<x>0</x>
<y>0</y>
<width>291</width>
<height>190</height>
<width>373</width>
<height>166</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<item rowspan="3" row="0" column="0" >
<widget class="QGroupBox" name="versionBox" >
<property name="title" >
<string>Version</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QRadioButton" name="icmp4Button" >
<property name="text" >
<string>ICMPv4</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="icmp6Button" >
<property name="text" >
<string>ICMPv6</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>Type</string>
@ -23,10 +46,10 @@
</property>
</widget>
</item>
<item row="0" column="1" >
<item row="0" column="2" >
<widget class="IntComboBox" name="typeCombo" />
</item>
<item row="1" column="0" >
<item row="1" column="1" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Code</string>
@ -36,46 +59,43 @@
</property>
</widget>
</item>
<item row="1" column="1" >
<item row="1" column="2" >
<widget class="QLineEdit" name="codeEdit" />
</item>
<item row="2" column="0" >
<widget class="QCheckBox" name="overrideCksum" >
<property name="text" >
<string>Checksum</string>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QLineEdit" name="cksumEdit" >
<property name="enabled" >
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="2" >
<item row="1" column="3" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<width>31</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="2" >
<widget class="QFrame" name="idSeqFrame" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
<item row="2" column="1" >
<widget class="QCheckBox" name="overrideCksum" >
<property name="text" >
<string>Checksum</string>
</property>
<property name="frameShadow" >
<enum>QFrame::Plain</enum>
</widget>
</item>
<item row="2" column="2" >
<widget class="QLineEdit" name="cksumEdit" >
<property name="enabled" >
<bool>false</bool>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
</widget>
</item>
<item row="3" column="0" colspan="3" >
<widget class="QGroupBox" name="idSeqFrame" >
<property name="title" >
<string/>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>Identifier</string>
@ -85,10 +105,10 @@
</property>
</widget>
</item>
<item row="0" column="1" >
<item>
<widget class="QLineEdit" name="idEdit" />
</item>
<item row="1" column="0" >
<item>
<widget class="QLabel" name="label_5" >
<property name="text" >
<string>Sequence</string>
@ -98,21 +118,21 @@
</property>
</widget>
</item>
<item row="1" column="1" >
<item>
<widget class="QLineEdit" name="seqEdit" />
</item>
</layout>
</widget>
</item>
<item row="4" column="0" colspan="2" >
<item row="4" column="0" colspan="3" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>137</width>
<height>16</height>
<width>211</width>
<height>71</height>
</size>
</property>
</spacer>
@ -127,6 +147,8 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>icmp4Button</tabstop>
<tabstop>icmp6Button</tabstop>
<tabstop>typeCombo</tabstop>
<tabstop>codeEdit</tabstop>
<tabstop>overrideCksum</tabstop>