Implemented MLD PDML Protocol - also ICMPv6 PDML protocol which detects and hands over control to either the ICMP PDML Protocol or MLD PDML Protocol

This commit is contained in:
Srivats P. 2011-04-08 20:44:32 +05:30
parent 41738b3e08
commit f132e3118c
3 changed files with 286 additions and 8 deletions

View File

@ -385,7 +385,7 @@ QVariant MldProtocol::fieldData(int index, FieldAttrib attrib,
qToBigEndian(rec.sources(j).v6_hi(), qToBigEndian(rec.sources(j).v6_hi(),
(uchar*)(rv.data()+20+16*j)); (uchar*)(rv.data()+20+16*j));
qToBigEndian(rec.sources(j).v6_lo(), qToBigEndian(rec.sources(j).v6_lo(),
(uchar*)(rv.data()+20+16*j)); (uchar*)(rv.data()+20+16*j+8));
} }
fv.append(rv); fv.append(rv);

View File

@ -34,6 +34,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "igmp.pb.h" #include "igmp.pb.h"
#include "ip4.pb.h" #include "ip4.pb.h"
#include "ip6.pb.h" #include "ip6.pb.h"
#include "mld.pb.h"
#include "sample.pb.h"
#include "snap.pb.h" #include "snap.pb.h"
#include "svlan.pb.h" #include "svlan.pb.h"
#include "tcp.pb.h" #include "tcp.pb.h"
@ -213,7 +215,7 @@ PdmlReader::PdmlReader(OstProto::StreamConfigList *streams)
factory_.insert("eth", PdmlEthProtocol::createInstance); factory_.insert("eth", PdmlEthProtocol::createInstance);
factory_.insert("http", PdmlTextProtocol::createInstance); factory_.insert("http", PdmlTextProtocol::createInstance);
factory_.insert("icmp", PdmlIcmpProtocol::createInstance); factory_.insert("icmp", PdmlIcmpProtocol::createInstance);
factory_.insert("icmpv6", PdmlIcmpProtocol::createInstance); factory_.insert("icmpv6", PdmlIcmp6Protocol::createInstance);
factory_.insert("igmp", PdmlIgmpProtocol::createInstance); factory_.insert("igmp", PdmlIgmpProtocol::createInstance);
factory_.insert("ieee8021ad", PdmlSvlanProtocol::createInstance); factory_.insert("ieee8021ad", PdmlSvlanProtocol::createInstance);
factory_.insert("imap", PdmlTextProtocol::createInstance); factory_.insert("imap", PdmlTextProtocol::createInstance);
@ -1047,7 +1049,37 @@ void PdmlEthProtocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlStreamAttributes &attributes, const QXmlStreamAttributes &attributes,
OstProto::Protocol *pbProto, OstProto::Stream *stream) OstProto::Protocol *pbProto, OstProto::Stream *stream)
{ {
if (name == "eth.type") if (name == "eth.vlan.tpid")
{
bool isOk;
uint tpid = attributes.value("value").toString()
.toUInt(&isOk, kBaseHex);
OstProto::Protocol *proto = stream->add_protocol();
proto->mutable_protocol_id()->set_id(
OstProto::Protocol::kVlanFieldNumber);
OstProto::Vlan *vlan = proto->MutableExtension(OstProto::vlan);
vlan->set_tpid(tpid);
vlan->set_is_override_tpid(true);
}
else if (name == "eth.vlan.id")
{
bool isOk;
uint tag = attributes.value("unmaskedvalue").isEmpty() ?
attributes.value("value").toString().toUInt(&isOk, kBaseHex) :
attributes.value("unmaskedvalue").toString().toUInt(&isOk,kBaseHex);
OstProto::Vlan *vlan = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::vlan);
vlan->set_vlan_tag(tag);
}
else if (name == "eth.type")
{ {
bool isOk; bool isOk;
@ -1332,8 +1364,10 @@ PdmlIcmpProtocol::PdmlIcmpProtocol()
fieldMap_.insert("icmpv6.type", OstProto::Icmp::kTypeFieldNumber); fieldMap_.insert("icmpv6.type", OstProto::Icmp::kTypeFieldNumber);
fieldMap_.insert("icmpv6.code", OstProto::Icmp::kCodeFieldNumber); fieldMap_.insert("icmpv6.code", OstProto::Icmp::kCodeFieldNumber);
fieldMap_.insert("icmpv6.checksum", OstProto::Icmp::kChecksumFieldNumber); fieldMap_.insert("icmpv6.checksum", OstProto::Icmp::kChecksumFieldNumber);
// ICMPv6 ident and seq need to be handled as 'unknown' since Wireshark fieldMap_.insert("icmpv6.echo.identifier",
// doesn't define display filters for the same OstProto::Icmp::kIdentifierFieldNumber);
fieldMap_.insert("icmpv6.echo.sequence_number",
OstProto::Icmp::kSequenceFieldNumber);
} }
PdmlDefaultProtocol* PdmlIcmpProtocol::createInstance() PdmlDefaultProtocol* PdmlIcmpProtocol::createInstance()
@ -1370,6 +1404,7 @@ void PdmlIcmpProtocol::unknownFieldHandler(QString name, int pos, int size,
{ {
QString addrHexStr = attributes.value("value").toString(); QString addrHexStr = attributes.value("value").toString();
// Wireshark 1.4.x does not have these as filterable fields
if (attributes.value("show").toString().startsWith("ID")) if (attributes.value("show").toString().startsWith("ID"))
icmp->set_identifier(addrHexStr.toUInt(&isOk, kBaseHex)); icmp->set_identifier(addrHexStr.toUInt(&isOk, kBaseHex));
else if (attributes.value("show").toString().startsWith("Sequence")) else if (attributes.value("show").toString().startsWith("Sequence"))
@ -1386,6 +1421,87 @@ void PdmlIcmpProtocol::postProtocolHandler(OstProto::Protocol *pbProto,
stream->mutable_protocol()->RemoveLast(); stream->mutable_protocol()->RemoveLast();
} }
// ---------------------------------------------------------- //
// PdmlIcmp6Protocol //
// ---------------------------------------------------------- //
PdmlIcmp6Protocol::PdmlIcmp6Protocol()
{
pdmlProtoName_ = "icmpv6";
ostProtoId_ = OstProto::Protocol::kSampleFieldNumber;
proto_ = NULL;
}
PdmlDefaultProtocol* PdmlIcmp6Protocol::createInstance()
{
return new PdmlIcmp6Protocol();
}
void PdmlIcmp6Protocol::preProtocolHandler(QString name,
const QXmlStreamAttributes &attributes,
int expectedPos, OstProto::Protocol *pbProto,
OstProto::Stream *stream)
{
proto_ = NULL;
ostProtoId_ = OstProto::Protocol::kSampleFieldNumber;
icmp_.preProtocolHandler(name, attributes, expectedPos, pbProto, stream);
mld_.preProtocolHandler(name, attributes, expectedPos, pbProto, stream);
}
void PdmlIcmp6Protocol::postProtocolHandler(OstProto::Protocol *pbProto,
OstProto::Stream *stream)
{
if (proto_)
proto_->postProtocolHandler(pbProto, stream);
else
stream->mutable_protocol()->RemoveLast();
proto_ = NULL;
ostProtoId_ = OstProto::Protocol::kSampleFieldNumber;
}
void PdmlIcmp6Protocol::unknownFieldHandler(QString name,
int pos, int size, const QXmlStreamAttributes &attributes,
OstProto::Protocol *pbProto, OstProto::Stream *stream)
{
if (proto_)
{
proto_->unknownFieldHandler(name, pos, size, attributes, pbProto,
stream);
}
else if (name == "icmpv6.type")
{
bool isOk;
uint type = attributes.value("value").toString().toUInt(
&isOk, kBaseHex);
if (((type >= 130) && (type <= 132)) || (type == 143))
{
// MLD
proto_ = &mld_;
fieldMap_ = mld_.fieldMap_;
ostProtoId_ = OstProto::Protocol::kMldFieldNumber;
}
else
{
// ICMP
proto_ = &icmp_;
fieldMap_ = icmp_.fieldMap_;
ostProtoId_ = OstProto::Protocol::kIcmpFieldNumber;
}
pbProto->mutable_protocol_id()->set_id(ostProtoId_);
pbProto->MutableExtension(OstProto::sample)->Clear();
fieldHandler(name, attributes, pbProto, stream);
}
else
{
qDebug("unexpected field %s", name.toAscii().constData());
}
}
// ---------------------------------------------------------- // // ---------------------------------------------------------- //
// PdmlIgmpProtocol // // PdmlIgmpProtocol //
@ -1439,7 +1555,7 @@ void PdmlIgmpProtocol::unknownFieldHandler(QString name, int pos, int size,
{ {
version_ = attributes.value("show").toString().toUInt(&isOk); version_ = attributes.value("show").toString().toUInt(&isOk);
} }
if (name == "igmp.type") else if (name == "igmp.type")
{ {
uint type = valueHexStr.toUInt(&isOk, kBaseHex); uint type = valueHexStr.toUInt(&isOk, kBaseHex);
if (type == kIgmpQuery) if (type == kIgmpQuery)
@ -1453,7 +1569,7 @@ void PdmlIgmpProtocol::unknownFieldHandler(QString name, int pos, int size,
} }
igmp->set_type(type); igmp->set_type(type);
} }
if (name == "igmp.record_type") else if (name == "igmp.record_type")
{ {
OstProto::Gmp::GroupRecord *rec = igmp->add_group_records(); OstProto::Gmp::GroupRecord *rec = igmp->add_group_records();
rec->set_type(OstProto::Gmp::GroupRecord::RecordType( rec->set_type(OstProto::Gmp::GroupRecord::RecordType(
@ -1504,11 +1620,129 @@ void PdmlIgmpProtocol::unknownFieldHandler(QString name, int pos, int size,
void PdmlIgmpProtocol::postProtocolHandler(OstProto::Protocol *pbProto, void PdmlIgmpProtocol::postProtocolHandler(OstProto::Protocol *pbProto,
OstProto::Stream *stream) OstProto::Stream *stream)
{ {
// version is 0 for IGMP like protocols such as RGMP which we don't
// support currently
if (version_ == 0) if (version_ == 0)
stream->mutable_protocol()->RemoveLast(); stream->mutable_protocol()->RemoveLast();
} }
// ---------------------------------------------------------- //
// PdmlMldProtocol //
// ---------------------------------------------------------- //
PdmlMldProtocol::PdmlMldProtocol()
{
pdmlProtoName_ = "mld";
ostProtoId_ = OstProto::Protocol::kMldFieldNumber;
fieldMap_.insert("icmpv6.code", OstProto::Gmp::kRsvdCodeFieldNumber);
fieldMap_.insert("icmpv6.checksum", OstProto::Gmp::kChecksumFieldNumber);
fieldMap_.insert("icmpv6.mld.maximum_response_delay",
OstProto::Gmp::kMaxResponseTimeFieldNumber); // FIXME
fieldMap_.insert("icmpv6.mld.flag.s", OstProto::Gmp::kSFlagFieldNumber);
fieldMap_.insert("icmpv6.mld.flag.qrv", OstProto::Gmp::kQrvFieldNumber);
fieldMap_.insert("icmpv6.mld.qqi", OstProto::Gmp::kQqiFieldNumber); // FIXME
fieldMap_.insert("icmpv6.mld.nb_sources",
OstProto::Gmp::kSourceCountFieldNumber);
fieldMap_.insert("icmpv6.mldr.nb_mcast_records",
OstProto::Gmp::kGroupRecordCountFieldNumber);
}
PdmlDefaultProtocol* PdmlMldProtocol::createInstance()
{
return new PdmlMldProtocol();
}
void PdmlMldProtocol::preProtocolHandler(QString name,
const QXmlStreamAttributes &attributes, int expectedPos,
OstProto::Protocol *pbProto, OstProto::Stream *stream)
{
bool isOk;
OstProto::Gmp *mld = pbProto->MutableExtension(OstProto::mld);
mld->set_is_override_rsvd_code(true);
mld->set_is_override_checksum(true);
mld->set_is_override_source_count(true);
mld->set_is_override_group_record_count(true);
protoSize_ = attributes.value("size").toString().toUInt(&isOk);
}
void PdmlMldProtocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlStreamAttributes &attributes, OstProto::Protocol *pbProto,
OstProto::Stream *stream)
{
bool isOk;
OstProto::Gmp *mld = pbProto->MutableExtension(OstProto::mld);
QString valueHexStr = attributes.value("value").toString();
if (name == "icmpv6.type")
{
uint type = valueHexStr.toUInt(&isOk, kBaseHex);
if ((type == kMldQuery) && (protoSize_ >= 28))
type = kMldV2Query;
mld->set_type(type);
}
else if (name == "icmpv6.mld.multicast_address")
{
mld->mutable_group_address()->set_v6_hi(
valueHexStr.left(16).toULongLong(&isOk, kBaseHex));
mld->mutable_group_address()->set_v6_lo(
valueHexStr.right(16).toULongLong(&isOk, kBaseHex));
}
else if (name == "icmpv6.mld.source_address")
{
OstProto::Gmp::IpAddress *ip = mld->add_sources();
ip->set_v6_hi(valueHexStr.left(16).toULongLong(&isOk, kBaseHex));
ip->set_v6_lo(valueHexStr.right(16).toULongLong(&isOk, kBaseHex));
}
else if (name == "icmpv6.mldr.mar.record_type")
{
OstProto::Gmp::GroupRecord *rec = mld->add_group_records();
rec->set_type(OstProto::Gmp::GroupRecord::RecordType(
valueHexStr.toUInt(&isOk, kBaseHex)));
rec->set_is_override_source_count(true);
rec->set_is_override_aux_data_length(true);
}
else if (name == "icmpv6.mldr.mar.aux_data_len")
{
mld->mutable_group_records(mld->group_records_size() - 1)->
set_aux_data_length(valueHexStr.toUInt(&isOk, kBaseHex));
}
else if (name == "icmpv6.mldr.mar.nb_sources")
{
mld->mutable_group_records(mld->group_records_size() - 1)->
set_source_count(valueHexStr.toUInt(&isOk, kBaseHex));
}
else if (name == "icmpv6.mldr.mar.multicast_address")
{
OstProto::Gmp::IpAddress *ip = mld->mutable_group_records(
mld->group_records_size() - 1)->mutable_group_address();
ip->set_v6_hi(valueHexStr.left(16).toULongLong(&isOk, kBaseHex));
ip->set_v6_lo(valueHexStr.right(16).toULongLong(&isOk, kBaseHex));
}
else if (name == "icmpv6.mldr.mar.source_address")
{
OstProto::Gmp::IpAddress *ip = mld->mutable_group_records(
mld->group_records_size() - 1)->add_sources();
ip->set_v6_hi(valueHexStr.left(16).toULongLong(&isOk, kBaseHex));
ip->set_v6_lo(valueHexStr.right(16).toULongLong(&isOk, kBaseHex));
}
else if (name == "icmpv6.mldr.mar.auxiliary_data")
{
QByteArray ba = QByteArray::fromHex(
attributes.value("value").toString().toUtf8());
mld->mutable_group_records(mld->group_records_size() - 1)->
set_aux_data(ba.constData(), ba.size());
}
}
// ---------------------------------------------------------- // // ---------------------------------------------------------- //
// PdmlTcpProtocol // // PdmlTcpProtocol //
// ---------------------------------------------------------- // // ---------------------------------------------------------- //

View File

@ -250,6 +250,7 @@ public:
class PdmlIcmpProtocol : public PdmlDefaultProtocol class PdmlIcmpProtocol : public PdmlDefaultProtocol
{ {
friend class PdmlIcmp6Protocol;
public: public:
PdmlIcmpProtocol(); PdmlIcmpProtocol();
@ -270,6 +271,50 @@ private:
static const uint kIcmp6EchoReply = 129; static const uint kIcmp6EchoReply = 129;
}; };
class PdmlMldProtocol : public PdmlDefaultProtocol
{
friend class PdmlIcmp6Protocol;
public:
PdmlMldProtocol();
static PdmlDefaultProtocol* createInstance();
virtual void preProtocolHandler(QString name,
const QXmlStreamAttributes &attributes, int expectedPos,
OstProto::Protocol *pbProto, OstProto::Stream *stream);
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlStreamAttributes &attributes,
OstProto::Protocol *pbProto, OstProto::Stream *stream);
private:
static const uint kMldQuery = 0x82;
static const uint kMldV1Query = 0x82;
static const uint kMldV2Query = 0xFF82;
uint protoSize_;
};
class PdmlIcmp6Protocol : public PdmlDefaultProtocol
{
public:
PdmlIcmp6Protocol();
static PdmlDefaultProtocol* createInstance();
virtual void preProtocolHandler(QString name,
const QXmlStreamAttributes &attributes, int expectedPos,
OstProto::Protocol *pbProto, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Protocol *pbProto,
OstProto::Stream *stream);
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlStreamAttributes &attributes,
OstProto::Protocol *pbProto, OstProto::Stream *stream);
private:
PdmlIcmpProtocol icmp_;
PdmlMldProtocol mld_;
PdmlDefaultProtocol *proto_;
};
class PdmlIgmpProtocol : public PdmlDefaultProtocol class PdmlIgmpProtocol : public PdmlDefaultProtocol
{ {
public: public:
@ -292,7 +337,6 @@ private:
static const uint kIgmpV3Query = 0xFE11; static const uint kIgmpV3Query = 0xFE11;
uint version_; uint version_;
}; };
class PdmlTcpProtocol : public PdmlDefaultProtocol class PdmlTcpProtocol : public PdmlDefaultProtocol