2011-01-30 06:08:03 -06:00
|
|
|
/*
|
|
|
|
Copyright (C) 2010 Srivats P.
|
|
|
|
|
|
|
|
This file is part of "Ostinato"
|
|
|
|
|
|
|
|
This is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "pdml_p.h"
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
#include "abstractprotocol.h"
|
|
|
|
#include "pcapfileformat.h"
|
|
|
|
#include "protocolmanager.h"
|
|
|
|
#include "streambase.h"
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
#include "mac.pb.h"
|
|
|
|
#include "eth2.pb.h"
|
2011-03-06 07:11:08 -06:00
|
|
|
#include "dot3.pb.h"
|
2011-01-30 06:08:03 -06:00
|
|
|
#include "hexdump.pb.h"
|
2011-02-10 12:00:58 -06:00
|
|
|
#include "ip4.pb.h"
|
|
|
|
#include "ip6.pb.h"
|
|
|
|
#include "tcp.pb.h"
|
2011-01-30 06:08:03 -06:00
|
|
|
|
|
|
|
#include <google/protobuf/descriptor.h>
|
|
|
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
extern ProtocolManager *OstProtocolManager;
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
const int kBaseHex = 16;
|
|
|
|
|
2011-02-23 09:58:32 -06:00
|
|
|
static PdmlReader *gPdmlReader = NULL;
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
PdmlDefaultProtocol::PdmlDefaultProtocol()
|
|
|
|
{
|
|
|
|
ostProtoId_ = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
PdmlDefaultProtocol::~PdmlDefaultProtocol()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlDefaultProtocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlDefaultProtocol();
|
|
|
|
}
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
QString PdmlDefaultProtocol::pdmlProtoName() const
|
|
|
|
{
|
|
|
|
return pdmlProtoName_;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PdmlDefaultProtocol::ostProtoId() const
|
|
|
|
{
|
|
|
|
return ostProtoId_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PdmlDefaultProtocol::hasField(QString name) const
|
|
|
|
{
|
|
|
|
return fieldMap_.contains(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
int PdmlDefaultProtocol::fieldId(QString name) const
|
|
|
|
{
|
|
|
|
return fieldMap_.value(name);
|
|
|
|
}
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
void PdmlDefaultProtocol::preProtocolHandler(QString /*name*/,
|
|
|
|
const QXmlStreamAttributes& /*attributes*/,
|
|
|
|
int /*expectedPos*/, OstProto::Stream* /*stream*/)
|
2011-02-18 12:02:57 -06:00
|
|
|
{
|
|
|
|
return; // do nothing!
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlDefaultProtocol::prematureEndHandler(int pos, OstProto::Stream *stream)
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
|
|
|
return; // do nothing!
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlDefaultProtocol::postProtocolHandler(OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
return; // do nothing!
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlDefaultProtocol::unknownFieldHandler(QString name,
|
2011-02-18 12:02:57 -06:00
|
|
|
int pos, int size, const QXmlStreamAttributes &attributes,
|
2011-01-30 06:08:03 -06:00
|
|
|
OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
return; // do nothing!
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlReader //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
PdmlReader::PdmlReader(OstProto::StreamConfigList *streams)
|
|
|
|
{
|
2011-02-23 09:58:32 -06:00
|
|
|
gPdmlReader = this;
|
2011-03-06 07:11:08 -06:00
|
|
|
pcap_ = NULL;
|
2011-02-23 09:58:32 -06:00
|
|
|
pass_ = 0;
|
2011-02-18 12:02:57 -06:00
|
|
|
streams_ = streams;
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
currentStream_ = NULL;
|
|
|
|
prevStream_ = NULL;
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
factory_.insert("hexdump", PdmlUnknownProtocol::createInstance);
|
|
|
|
factory_.insert("geninfo", PdmlGenInfoProtocol::createInstance);
|
|
|
|
factory_.insert("frame", PdmlFrameProtocol::createInstance);
|
|
|
|
#if 0
|
|
|
|
factory_.insert("fake-field-wrapper",
|
|
|
|
new PdmlFakeFieldWrapperProtocol());
|
2011-03-06 07:11:08 -06:00
|
|
|
#endif
|
2011-02-18 12:02:57 -06:00
|
|
|
factory_.insert("eth",PdmlEthProtocol::createInstance);
|
|
|
|
factory_.insert("ip",PdmlIp4Protocol::createInstance);
|
|
|
|
factory_.insert("ipv6",PdmlIp6Protocol::createInstance);
|
|
|
|
factory_.insert("tcp",PdmlTcpProtocol::createInstance);
|
|
|
|
}
|
|
|
|
|
|
|
|
PdmlReader::~PdmlReader()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
bool PdmlReader::read(QIODevice *device, PcapFileFormat *pcap)
|
2011-02-18 12:02:57 -06:00
|
|
|
{
|
|
|
|
setDevice(device);
|
2011-03-06 07:11:08 -06:00
|
|
|
pcap_ = pcap;
|
2011-02-18 12:02:57 -06:00
|
|
|
packetCount_ = 0;
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
#if 0
|
2011-02-23 09:58:32 -06:00
|
|
|
// 1st pass - preprocessing fake fields
|
|
|
|
pass_ = 1;
|
|
|
|
qDebug("PASS %d\n", pass_);
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "pdml")
|
|
|
|
readPdml();
|
|
|
|
else
|
|
|
|
raiseError("Not a pdml file!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clear();
|
|
|
|
device->seek(0);
|
|
|
|
setDevice(device);
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
#endif
|
2011-02-23 09:58:32 -06:00
|
|
|
// 2nd pass - actual processing
|
|
|
|
pass_ = 2;
|
|
|
|
qDebug("PASS %d\n", pass_);
|
2011-02-18 12:02:57 -06:00
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "pdml")
|
|
|
|
readPdml();
|
|
|
|
else
|
|
|
|
raiseError("Not a pdml file!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
if (error())
|
|
|
|
{
|
|
|
|
qDebug("Line %lld", lineNumber());
|
|
|
|
qDebug("Col %lld", columnNumber());
|
|
|
|
qDebug("%s", errorString().toAscii().constData()); // FIXME
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2011-02-18 12:02:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: use a temp pool to avoid a lot of new/delete
|
|
|
|
PdmlDefaultProtocol* PdmlReader::allocPdmlProtocol(QString protoName)
|
|
|
|
{
|
|
|
|
if (!factory_.contains(protoName))
|
|
|
|
protoName = "hexdump";
|
|
|
|
|
|
|
|
return (*(factory_.value(protoName)))();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlReader::freePdmlProtocol(PdmlDefaultProtocol *proto)
|
|
|
|
{
|
|
|
|
delete proto;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PdmlReader::isDontCareProto()
|
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement() && name() == "proto");
|
|
|
|
|
|
|
|
QString protoName = attributes().value("name").toString();
|
|
|
|
|
|
|
|
if (protoName.isEmpty() || (protoName == "expert"))
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlReader::readUnexpectedElement()
|
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement());
|
|
|
|
|
|
|
|
// XXX: add to 'log'
|
|
|
|
qDebug("unexpected element - <%s>; skipping ...",
|
|
|
|
name().toString().toAscii().constData());
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlReader::skipElement()
|
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement());
|
|
|
|
|
|
|
|
// XXX: add to 'log'
|
|
|
|
qDebug("skipping element - <%s>",
|
|
|
|
name().toString().toAscii().constData());
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
skipElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlReader::readPdml()
|
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement() && name() == "pdml");
|
|
|
|
|
2011-02-23 09:58:32 -06:00
|
|
|
packetCount_ = 1;
|
2011-02-18 12:02:57 -06:00
|
|
|
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "packet")
|
2011-02-23 09:58:32 -06:00
|
|
|
{
|
|
|
|
if (pass_ == 1)
|
|
|
|
readPacketPass1();
|
|
|
|
else if (pass_ == 2)
|
|
|
|
readPacket();
|
|
|
|
else
|
|
|
|
Q_ASSERT(false); // unreachable!
|
|
|
|
}
|
2011-02-18 12:02:57 -06:00
|
|
|
else
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
/////////////////////// PASS 1 //////////////////////////
|
|
|
|
|
2011-02-23 09:58:32 -06:00
|
|
|
void PdmlReader::readPacketPass1()
|
2011-02-18 12:02:57 -06:00
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement() && name() == "packet");
|
|
|
|
|
2011-02-23 09:58:32 -06:00
|
|
|
qDebug("Pass1 packetNum = %d", packetCount_);
|
|
|
|
|
|
|
|
Fragment f;
|
|
|
|
f.pos = -1;
|
|
|
|
f.size = -1;
|
|
|
|
f.value = QByteArray();
|
|
|
|
|
|
|
|
pktFragments_.append(f);
|
|
|
|
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "proto")
|
|
|
|
readProtoPass1();
|
|
|
|
else if (name() == "field")
|
|
|
|
skipElement();
|
|
|
|
else
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
2011-02-18 12:02:57 -06:00
|
|
|
packetCount_++;
|
2011-02-23 09:58:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlReader::readProtoPass1()
|
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement() && name() == "proto");
|
|
|
|
|
|
|
|
if (attributes().value("name") != "fake-field-wrapper")
|
|
|
|
{
|
|
|
|
skipElement();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "proto")
|
|
|
|
readProtoPass1();
|
|
|
|
else if (name() == "field")
|
|
|
|
readFieldPass1();
|
|
|
|
else
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlReader::readFieldPass1()
|
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement() && name() == "field");
|
|
|
|
|
|
|
|
if (attributes().value("name") != "data.data")
|
|
|
|
{
|
|
|
|
skipElement();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString fieldName = attributes().value("name").toString();
|
|
|
|
QString valueHexStr = attributes().value("value").toString();
|
|
|
|
int pos = -1;
|
|
|
|
int size = -1;
|
|
|
|
|
|
|
|
if (!attributes().value("pos").isEmpty())
|
|
|
|
pos = attributes().value("pos").toString().toInt();
|
|
|
|
if (!attributes().value("size").isEmpty())
|
|
|
|
size = attributes().value("size").toString().toInt();
|
|
|
|
|
|
|
|
qDebug("\tFAKE FIELD fieldName:%s, pos:%d, size:%d value:%s",
|
|
|
|
fieldName.toAscii().constData(),
|
|
|
|
pos,
|
|
|
|
size,
|
|
|
|
valueHexStr.toAscii().constData());
|
|
|
|
|
|
|
|
pktFragments_[packetCount_-1].pos = pos;
|
|
|
|
pktFragments_[packetCount_-1].size = size;
|
|
|
|
pktFragments_[packetCount_-1].value =
|
|
|
|
QByteArray::fromHex(valueHexStr.toUtf8());
|
|
|
|
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "proto")
|
|
|
|
readProtoPass1();
|
|
|
|
else if (name() == "field")
|
|
|
|
readFieldPass1();
|
|
|
|
else
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
/////////////////////// PASS 2 //////////////////////////
|
|
|
|
|
2011-02-23 09:58:32 -06:00
|
|
|
void PdmlReader::readPacket()
|
|
|
|
{
|
2011-03-06 07:11:08 -06:00
|
|
|
PcapFileFormat::PcapPacketHeader pktHdr;
|
|
|
|
|
|
|
|
Q_ASSERT(isStartElement() && name() == "packet");
|
2011-02-23 09:58:32 -06:00
|
|
|
|
|
|
|
qDebug("%s: packetNum = %d", __FUNCTION__, packetCount_);
|
2011-02-18 12:02:57 -06:00
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
skipUntilEnd_ = false;
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
// XXX: we play dumb and convert each packet to a stream, for now
|
2011-03-12 03:46:27 -06:00
|
|
|
prevStream_ = currentStream_;
|
2011-02-18 12:02:57 -06:00
|
|
|
currentStream_ = streams_->add_stream();
|
|
|
|
currentStream_->mutable_stream_id()->set_id(packetCount_);
|
|
|
|
currentStream_->mutable_core()->set_is_enabled(true);
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
// Set to a high number; will get reset to correct during parse
|
|
|
|
currentStream_->mutable_core()->set_frame_len(16384); // FIXME: Hard coding!
|
|
|
|
|
|
|
|
expPos_ = 0;
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
if (pcap_)
|
|
|
|
pcap_->readPacket(pktHdr, pktBuf_);
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
2011-03-12 03:46:27 -06:00
|
|
|
if (skipUntilEnd_)
|
|
|
|
skipElement();
|
|
|
|
else if (name() == "proto")
|
2011-02-18 12:02:57 -06:00
|
|
|
readProto();
|
|
|
|
else if (name() == "field")
|
|
|
|
readField(NULL, NULL); // TODO: top level field!!!!
|
|
|
|
else
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
2011-03-12 03:46:27 -06:00
|
|
|
// BAD Hack for TCP Segments
|
2011-02-18 12:02:57 -06:00
|
|
|
if (currentStream_->core().name().size())
|
2011-03-12 03:46:27 -06:00
|
|
|
#if 0
|
2011-02-18 12:02:57 -06:00
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = currentStream_->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kHexDumpFieldNumber);
|
|
|
|
|
|
|
|
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
qDebug("Adding TCP Segment Data/FCS etc of size %d",
|
|
|
|
currentStream_->core().name().size());
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
hexDump->set_content(currentStream_->core().name());
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
currentStream_->mutable_core()->set_name("");
|
2011-03-12 03:46:27 -06:00
|
|
|
|
|
|
|
expPos_ += hexDump->content().size();
|
2011-02-18 12:02:57 -06:00
|
|
|
}
|
2011-03-12 03:46:27 -06:00
|
|
|
#else
|
|
|
|
currentStream_->mutable_core()->set_name("");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// If trailing bytes are missing, add those from the pcap
|
|
|
|
if ((expPos_ < pktBuf_.size()) && pcap_)
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = currentStream_->add_protocol();
|
|
|
|
OstProto::HexDump *hexDump = proto->MutableExtension(
|
|
|
|
OstProto::hexDump);
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kHexDumpFieldNumber);
|
|
|
|
|
|
|
|
qDebug("adding trailing %d bytes starting from %d",
|
|
|
|
pktBuf_.size() - expPos_, expPos_);
|
|
|
|
hexDump->set_content(pktBuf_.constData() + expPos_,
|
|
|
|
pktBuf_.size() - expPos_);
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
}
|
2011-02-18 12:02:57 -06:00
|
|
|
|
2011-02-23 09:58:32 -06:00
|
|
|
packetCount_++;
|
2011-03-12 03:46:27 -06:00
|
|
|
if (prevStream_)
|
|
|
|
prevStream_->mutable_control()->CopyFrom(currentStream_->control());
|
2011-02-23 09:58:32 -06:00
|
|
|
}
|
2011-02-18 12:02:57 -06:00
|
|
|
|
|
|
|
void PdmlReader::readProto()
|
|
|
|
{
|
|
|
|
PdmlDefaultProtocol *pdmlProto = NULL;
|
|
|
|
google::protobuf::Message *pbProto = NULL;
|
|
|
|
|
|
|
|
Q_ASSERT(isStartElement() && name() == "proto");
|
|
|
|
|
|
|
|
QString protoName = attributes().value("name").toString();
|
2011-03-06 07:11:08 -06:00
|
|
|
int pos = -1;
|
2011-03-12 03:46:27 -06:00
|
|
|
int size = -1;
|
2011-02-18 12:02:57 -06:00
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
if (!attributes().value("pos").isEmpty())
|
|
|
|
pos = attributes().value("pos").toString().toInt();
|
2011-03-12 03:46:27 -06:00
|
|
|
if (!attributes().value("size").isEmpty())
|
|
|
|
size = attributes().value("size").toString().toInt();
|
2011-03-06 07:11:08 -06:00
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
qDebug("proto: %s, pos = %d, expPos_ = %d",
|
|
|
|
protoName.toAscii().constData(), pos, expPos_);
|
2011-03-06 07:11:08 -06:00
|
|
|
|
|
|
|
// This is a heuristic to skip protocols which are not part of
|
|
|
|
// this frame, but of a reassembled segment spanning several frames
|
2011-03-12 03:46:27 -06:00
|
|
|
// 1. Proto starting pos is 0, but we already seen some protocols
|
|
|
|
// 2. Protocol Size exceeds frame length
|
|
|
|
if (((pos == 0) && (currentStream_->protocol_size() > 0))
|
|
|
|
|| ((pos + size) > int(currentStream_->core().frame_len())))
|
2011-03-06 07:11:08 -06:00
|
|
|
{
|
|
|
|
qDebug("(skipped)");
|
|
|
|
skipElement();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 1
|
2011-02-18 12:02:57 -06:00
|
|
|
if (protoName.isEmpty() || (protoName == "expert"))
|
|
|
|
{
|
|
|
|
skipElement();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
// detect overlaps or gaps between subsequent protocols and "fill-in"
|
|
|
|
// with a "hexdump" from the pcap
|
|
|
|
if (pos >=0 && pcap_)
|
|
|
|
{
|
|
|
|
if (pos > expPos_)
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = currentStream_->add_protocol();
|
|
|
|
OstProto::HexDump *hexDump = proto->MutableExtension(
|
|
|
|
OstProto::hexDump);
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kHexDumpFieldNumber);
|
|
|
|
|
|
|
|
qDebug("filling in gap of %d bytes starting from %d",
|
|
|
|
pos - expPos_, expPos_);
|
|
|
|
hexDump->set_content(pktBuf_.constData() + expPos_, pos - expPos_);
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
|
|
|
|
expPos_ = pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// for unknown protocol, read a hexdump from the pcap
|
2011-03-06 07:11:08 -06:00
|
|
|
if (!factory_.contains(protoName) && pcap_)
|
|
|
|
{
|
|
|
|
int size = -1;
|
|
|
|
|
|
|
|
if (!attributes().value("size").isEmpty())
|
|
|
|
size = attributes().value("size").toString().toInt();
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
|
|
|
|
// Check if this proto is a subset of previous proto - if so, do nothing
|
|
|
|
if ((pos >= 0) && (size > 0) && ((pos + size) <= expPos_))
|
|
|
|
{
|
|
|
|
qDebug("subset proto");
|
|
|
|
skipElement();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
if (pos >= 0 && size > 0
|
|
|
|
&& ((pos + size) <= pktBuf_.size()))
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = currentStream_->add_protocol();
|
|
|
|
OstProto::HexDump *hexDump = proto->MutableExtension(
|
|
|
|
OstProto::hexDump);
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kHexDumpFieldNumber);
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
qDebug("missing bytes - filling in %d bytes staring from %d",
|
|
|
|
size, pos);
|
2011-03-06 07:11:08 -06:00
|
|
|
hexDump->set_content(pktBuf_.constData() + pos, size);
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
|
|
|
|
skipElement();
|
2011-03-12 03:46:27 -06:00
|
|
|
|
|
|
|
expPos_ += size;
|
2011-03-06 07:11:08 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
pdmlProto = allocPdmlProtocol(protoName);
|
|
|
|
Q_ASSERT(pdmlProto != NULL);
|
|
|
|
|
|
|
|
int protoId = pdmlProto->ostProtoId();
|
|
|
|
|
|
|
|
// Non PdmlDefaultProtocol
|
|
|
|
if (protoId > 0)
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = currentStream_->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(protoId);
|
|
|
|
|
|
|
|
const google::protobuf::Reflection *msgRefl = proto->GetReflection();
|
|
|
|
const google::protobuf::FieldDescriptor *fieldDesc =
|
|
|
|
msgRefl->FindKnownExtensionByNumber(protoId);
|
|
|
|
|
|
|
|
// TODO: if !fDesc
|
|
|
|
// init default values of all fields in protocol
|
|
|
|
pbProto = msgRefl->MutableMessage(proto, fieldDesc);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
pdmlProto->preProtocolHandler(protoName, attributes(), expPos_,
|
|
|
|
currentStream_);
|
2011-02-18 12:02:57 -06:00
|
|
|
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "proto")
|
|
|
|
{
|
|
|
|
int endPos = -1;
|
|
|
|
// an embedded proto
|
|
|
|
qDebug("embedded proto: %s\n", attributes().value("name")
|
|
|
|
.toString().toAscii().constData());
|
|
|
|
if (isDontCareProto())
|
|
|
|
{
|
|
|
|
skipElement();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!attributes().value("pos").isEmpty())
|
|
|
|
endPos = attributes().value("pos").toString().toInt();
|
|
|
|
|
|
|
|
|
|
|
|
// pdmlProto may be NULL for a sequence of embedded protos
|
|
|
|
if (pdmlProto)
|
|
|
|
{
|
|
|
|
pdmlProto->prematureEndHandler(endPos, currentStream_);
|
|
|
|
pdmlProto->postProtocolHandler(currentStream_);
|
2011-03-12 03:46:27 -06:00
|
|
|
|
|
|
|
StreamBase s;
|
|
|
|
s.protoDataCopyFrom(*currentStream_);
|
|
|
|
expPos_ = s.frameProtocolLength(0);
|
2011-02-18 12:02:57 -06:00
|
|
|
}
|
|
|
|
readProto();
|
|
|
|
pdmlProto = NULL;
|
|
|
|
pbProto = NULL;
|
|
|
|
}
|
|
|
|
else if (name() == "field")
|
|
|
|
{
|
2011-03-12 03:46:27 -06:00
|
|
|
if ((protoName == "fake-field-wrapper") &&
|
|
|
|
(attributes().value("name") == "tcp.segments"))
|
|
|
|
{
|
|
|
|
skipElement();
|
|
|
|
qDebug("[skipping reassembled tcp segments]");
|
|
|
|
|
|
|
|
skipUntilEnd_ = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
if (pdmlProto == NULL)
|
|
|
|
{
|
|
|
|
pdmlProto = allocPdmlProtocol(protoName);
|
|
|
|
protoId = pdmlProto->ostProtoId();
|
|
|
|
|
|
|
|
// Non PdmlDefaultProtocol
|
|
|
|
if (protoId > 0)
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = currentStream_->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(protoId);
|
|
|
|
|
|
|
|
const google::protobuf::Reflection *msgRefl = proto->GetReflection();
|
|
|
|
const google::protobuf::FieldDescriptor *fieldDesc =
|
|
|
|
msgRefl->FindKnownExtensionByNumber(protoId);
|
|
|
|
|
|
|
|
// TODO: if !fDesc
|
|
|
|
// init default values of all fields in protocol
|
|
|
|
pbProto = msgRefl->MutableMessage(proto, fieldDesc);
|
|
|
|
|
|
|
|
}
|
2011-03-12 03:46:27 -06:00
|
|
|
pdmlProto->preProtocolHandler(protoName, attributes(),
|
|
|
|
expPos_, currentStream_);
|
2011-02-18 12:02:57 -06:00
|
|
|
}
|
|
|
|
readField(pdmlProto, pbProto);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pdmlProto)
|
|
|
|
{
|
|
|
|
pdmlProto->postProtocolHandler(currentStream_);
|
|
|
|
freePdmlProtocol(pdmlProto);
|
2011-03-12 03:46:27 -06:00
|
|
|
|
|
|
|
StreamBase s;
|
|
|
|
s.protoDataCopyFrom(*currentStream_);
|
|
|
|
expPos_ = s.frameProtocolLength(0);
|
2011-02-18 12:02:57 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlReader::readField(PdmlDefaultProtocol *pdmlProto,
|
|
|
|
google::protobuf::Message *pbProto)
|
|
|
|
{
|
|
|
|
Q_ASSERT(isStartElement() && name() == "field");
|
|
|
|
|
|
|
|
// fields with "hide='yes'" are informational and should be skipped
|
|
|
|
if (attributes().value("hide") == "yes")
|
|
|
|
{
|
|
|
|
skipElement();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString fieldName = attributes().value("name").toString();
|
|
|
|
QString valueHexStr = attributes().value("value").toString();
|
|
|
|
int pos = -1;
|
|
|
|
int size = -1;
|
|
|
|
|
|
|
|
if (!attributes().value("pos").isEmpty())
|
|
|
|
pos = attributes().value("pos").toString().toInt();
|
|
|
|
if (!attributes().value("size").isEmpty())
|
|
|
|
size = attributes().value("size").toString().toInt();
|
|
|
|
|
|
|
|
qDebug("\tfieldName:%s, pos:%d, size:%d value:%s",
|
|
|
|
fieldName.toAscii().constData(),
|
|
|
|
pos,
|
|
|
|
size,
|
|
|
|
valueHexStr.toAscii().constData());
|
|
|
|
|
|
|
|
if (pdmlProto->hasField(fieldName))
|
|
|
|
{
|
|
|
|
int fieldId = pdmlProto->fieldId(fieldName);
|
|
|
|
const google::protobuf::Descriptor *msgDesc =
|
|
|
|
pbProto->GetDescriptor();
|
|
|
|
const google::protobuf::FieldDescriptor *fieldDesc =
|
|
|
|
msgDesc->FindFieldByNumber(fieldId);
|
|
|
|
const google::protobuf::Reflection *msgRefl =
|
|
|
|
pbProto->GetReflection();
|
|
|
|
|
|
|
|
bool isOk;
|
|
|
|
|
|
|
|
switch(fieldDesc->cpp_type())
|
|
|
|
{
|
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: // TODO
|
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
|
|
|
|
msgRefl->SetUInt32(pbProto, fieldDesc,
|
|
|
|
valueHexStr.toUInt(&isOk, kBaseHex));
|
|
|
|
break;
|
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
|
|
|
msgRefl->SetUInt64(pbProto, fieldDesc,
|
|
|
|
valueHexStr.toULongLong(&isOk, kBaseHex));
|
|
|
|
break;
|
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
|
|
|
|
{
|
|
|
|
QByteArray hexVal = QByteArray::fromHex(valueHexStr.toUtf8());
|
|
|
|
std::string str(hexVal.constData(), hexVal.size());
|
|
|
|
msgRefl->SetString(pbProto, fieldDesc, str);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
qDebug("%s: unhandled cpptype = %d", __FUNCTION__,
|
|
|
|
fieldDesc->cpp_type());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pdmlProto->unknownFieldHandler(fieldName, pos, size, attributes(),
|
|
|
|
currentStream_);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!atEnd())
|
|
|
|
{
|
|
|
|
readNext();
|
|
|
|
|
|
|
|
if (isEndElement())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (isStartElement())
|
|
|
|
{
|
|
|
|
if (name() == "proto")
|
|
|
|
{
|
|
|
|
if (isDontCareProto())
|
|
|
|
{
|
|
|
|
skipElement();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
readProto();
|
|
|
|
}
|
|
|
|
else if (name() == "field")
|
|
|
|
readField(pdmlProto, pbProto);
|
|
|
|
else
|
|
|
|
readUnexpectedElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 06:08:03 -06:00
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlUnknownProtocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlUnknownProtocol::PdmlUnknownProtocol()
|
|
|
|
{
|
2011-02-18 12:02:57 -06:00
|
|
|
pdmlProtoName_ = "";
|
2011-01-30 06:08:03 -06:00
|
|
|
ostProtoId_ = OstProto::Protocol::kHexDumpFieldNumber;
|
|
|
|
|
|
|
|
endPos_ = expPos_ = -1;
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlUnknownProtocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlUnknownProtocol();
|
|
|
|
}
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
void PdmlUnknownProtocol::preProtocolHandler(QString name,
|
2011-03-12 03:46:27 -06:00
|
|
|
const QXmlStreamAttributes &attributes,
|
|
|
|
int expectedPos, OstProto::Stream *stream)
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
|
|
|
bool isOk;
|
2011-02-10 12:00:58 -06:00
|
|
|
int size;
|
2011-02-18 12:02:57 -06:00
|
|
|
int pos = attributes.value("pos").toString().toUInt(&isOk);
|
2011-02-10 12:00:58 -06:00
|
|
|
if (!isOk)
|
2011-03-12 03:46:27 -06:00
|
|
|
{
|
|
|
|
if (expectedPos >= 0)
|
|
|
|
expPos_ = pos = expectedPos;
|
|
|
|
else
|
|
|
|
goto _skip_pos_size_proc;
|
|
|
|
}
|
2011-01-30 06:08:03 -06:00
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
size = attributes.value("size").toString().toUInt(&isOk);
|
2011-02-10 12:00:58 -06:00
|
|
|
if (!isOk)
|
|
|
|
goto _skip_pos_size_proc;
|
2011-01-30 06:08:03 -06:00
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
// If pos+size goes beyond the frame length, this is a "reassembled"
|
|
|
|
// protocol and should be skipped
|
2011-03-12 03:46:27 -06:00
|
|
|
if ((pos + size) > int(stream->core().frame_len()))
|
2011-03-06 07:11:08 -06:00
|
|
|
goto _skip_pos_size_proc;
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
expPos_ = pos;
|
|
|
|
endPos_ = expPos_ + size;
|
2011-02-10 12:00:58 -06:00
|
|
|
|
|
|
|
_skip_pos_size_proc:
|
|
|
|
OstProto::HexDump *hexDump = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
|
|
|
|
hexDump->set_pad_until_end(false);
|
2011-01-30 06:08:03 -06:00
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
void PdmlUnknownProtocol::prematureEndHandler(int pos, OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
endPos_ = pos;
|
|
|
|
}
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
OstProto::HexDump *hexDump = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
// Skipped field(s) at end? Pad with zero!
|
2011-01-30 06:08:03 -06:00
|
|
|
if (endPos_ > expPos_)
|
|
|
|
{
|
|
|
|
QByteArray hexVal(endPos_ - expPos_, char(0));
|
|
|
|
|
|
|
|
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
|
|
|
|
expPos_ += hexVal.size();
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
qDebug(" hexdump: expPos_ = %d, endPos_ = %d\n", expPos_, endPos_);
|
2011-02-10 12:00:58 -06:00
|
|
|
//Q_ASSERT(expPos_ == endPos_);
|
2011-01-30 06:08:03 -06:00
|
|
|
|
|
|
|
hexDump->set_pad_until_end(false);
|
2011-03-12 03:46:27 -06:00
|
|
|
|
|
|
|
// If empty for some reason, remove the protocol
|
|
|
|
if (hexDump->content().size() == 0)
|
|
|
|
stream->mutable_protocol()->RemoveLast();
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
endPos_ = expPos_ = -1;
|
2011-01-30 06:08:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size,
|
2011-02-18 12:02:57 -06:00
|
|
|
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
|
|
|
OstProto::HexDump *hexDump = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
qDebug(" hexdump: %s, pos = %d, expPos_ = %d, endPos_ = %d\n",
|
|
|
|
name.toAscii().constData(),
|
2011-02-10 12:00:58 -06:00
|
|
|
pos, expPos_, endPos_);
|
2011-01-30 06:08:03 -06:00
|
|
|
|
|
|
|
// Skipped field? Pad with zero!
|
2011-02-10 12:00:58 -06:00
|
|
|
if ((pos > expPos_) && (expPos_ < endPos_))
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
2011-03-12 03:46:27 -06:00
|
|
|
#if 0
|
2011-02-23 09:58:32 -06:00
|
|
|
PdmlReader::Fragment f;
|
2011-01-30 06:08:03 -06:00
|
|
|
|
2011-02-23 09:58:32 -06:00
|
|
|
f = gPdmlReader->pktFragments_.value(stream->stream_id().id()-1);
|
|
|
|
|
|
|
|
if (expPos_ == f.pos)
|
|
|
|
{
|
|
|
|
hexDump->mutable_content()->append(f.value.constData(), f.size);
|
|
|
|
expPos_ += f.size;
|
|
|
|
}
|
|
|
|
else
|
2011-03-12 03:46:27 -06:00
|
|
|
#endif
|
2011-02-23 09:58:32 -06:00
|
|
|
{
|
|
|
|
QByteArray hexVal(pos - expPos_, char(0));
|
|
|
|
|
|
|
|
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
|
|
|
|
expPos_ += hexVal.size();
|
|
|
|
}
|
2011-01-30 06:08:03 -06:00
|
|
|
}
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
if ((pos == expPos_) /*&& (pos < endPos_)*/)
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
2011-02-10 12:00:58 -06:00
|
|
|
QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ?
|
2011-02-18 12:02:57 -06:00
|
|
|
QByteArray::fromHex(attributes.value("value").toString().toUtf8()) :
|
|
|
|
QByteArray::fromHex(attributes.value("unmaskedvalue").toString().toUtf8());
|
2011-01-30 06:08:03 -06:00
|
|
|
|
|
|
|
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
|
|
|
|
expPos_ += hexVal.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlGenInfoProtocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlGenInfoProtocol::PdmlGenInfoProtocol()
|
|
|
|
{
|
|
|
|
pdmlProtoName_ = "geninfo";
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlGenInfoProtocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlGenInfoProtocol();
|
|
|
|
}
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
#if 0 // done in frame proto
|
2011-01-30 06:08:03 -06:00
|
|
|
void PdmlGenInfoProtocol::unknownFieldHandler(QString name, int pos,
|
2011-02-18 12:02:57 -06:00
|
|
|
int size, const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
2011-03-12 03:46:27 -06:00
|
|
|
if (name == "len")
|
|
|
|
stream->mutable_core()->set_frame_len(size+4); // TODO:check FCS
|
2011-01-30 06:08:03 -06:00
|
|
|
}
|
2011-03-12 03:46:27 -06:00
|
|
|
#endif
|
2011-01-30 06:08:03 -06:00
|
|
|
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlFrameProtocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlFrameProtocol::PdmlFrameProtocol()
|
|
|
|
{
|
|
|
|
pdmlProtoName_ = "frame";
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlFrameProtocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlFrameProtocol();
|
|
|
|
}
|
|
|
|
|
2011-03-12 03:46:27 -06:00
|
|
|
void PdmlFrameProtocol::unknownFieldHandler(QString name, int pos,
|
|
|
|
int size, const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
if (name == "frame.len")
|
|
|
|
{
|
|
|
|
int len = -1;
|
|
|
|
|
|
|
|
if (!attributes.value("show").isEmpty())
|
|
|
|
len = attributes.value("show").toString().toInt();
|
|
|
|
stream->mutable_core()->set_frame_len(len+4); // TODO:check FCS
|
|
|
|
}
|
|
|
|
else if (name == "frame.time_delta")
|
|
|
|
{
|
|
|
|
if (!attributes.value("show").isEmpty())
|
|
|
|
{
|
|
|
|
QString delta = attributes.value("show").toString();
|
|
|
|
int decimal = delta.indexOf('.');
|
|
|
|
|
|
|
|
if (decimal >= 0)
|
|
|
|
{
|
|
|
|
const uint kNsecsInSec = 1000000000;
|
|
|
|
uint sec = delta.left(decimal).toUInt();
|
|
|
|
uint nsec = delta.mid(decimal+1).toUInt();
|
|
|
|
uint ipg = sec*kNsecsInSec + nsec;
|
|
|
|
|
|
|
|
if (ipg)
|
|
|
|
{
|
|
|
|
stream->mutable_control()->set_packets_per_sec(
|
|
|
|
kNsecsInSec/ipg);
|
|
|
|
}
|
|
|
|
|
|
|
|
qDebug("sec.nsec = %u.%u, ipg = %u", sec, nsec, ipg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
#if 1
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlFakeFieldWrapperProtocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlFakeFieldWrapperProtocol::PdmlFakeFieldWrapperProtocol()
|
|
|
|
{
|
|
|
|
pdmlProtoName_ = "OST:HexDump";
|
|
|
|
ostProtoId_ = OstProto::Protocol::kHexDumpFieldNumber;
|
|
|
|
|
|
|
|
expPos_ = -1;
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlFakeFieldWrapperProtocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlFakeFieldWrapperProtocol();
|
|
|
|
}
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
void PdmlFakeFieldWrapperProtocol::preProtocolHandler(QString name,
|
2011-03-12 03:46:27 -06:00
|
|
|
const QXmlStreamAttributes &attributes,
|
|
|
|
int expectedPos, OstProto::Stream *stream)
|
2011-02-10 12:00:58 -06:00
|
|
|
{
|
|
|
|
expPos_ = 0;
|
|
|
|
OstProto::HexDump *hexDump = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlFakeFieldWrapperProtocol::postProtocolHandler(OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
OstProto::HexDump *hexDump = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
|
|
|
|
|
|
|
|
qDebug("%s: expPos_ = %d\n", __FUNCTION__, expPos_);
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
// TODO: if content size is zero, remove protocol?
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
expPos_ = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlFakeFieldWrapperProtocol::unknownFieldHandler(QString name, int pos,
|
2011-02-18 12:02:57 -06:00
|
|
|
int size, const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
2011-02-10 12:00:58 -06:00
|
|
|
{
|
|
|
|
OstProto::HexDump *hexDump = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
|
|
|
|
|
|
|
|
if ((pos == expPos_) && (size >= 0) &&
|
2011-03-06 07:11:08 -06:00
|
|
|
(!name.startsWith("tcp.segment")) &&
|
2011-02-10 12:00:58 -06:00
|
|
|
(!attributes.value("unmaskedvalue").isEmpty() ||
|
|
|
|
!attributes.value("value").isEmpty()))
|
|
|
|
{
|
|
|
|
QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ?
|
2011-02-18 12:02:57 -06:00
|
|
|
QByteArray::fromHex(attributes.value("value").toString().toUtf8()) :
|
|
|
|
QByteArray::fromHex(attributes.value("unmaskedvalue").toString().toUtf8());
|
2011-01-30 06:08:03 -06:00
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
|
|
|
|
expPos_ += hexVal.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2011-01-30 06:08:03 -06:00
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlEthProtocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlEthProtocol::PdmlEthProtocol()
|
|
|
|
{
|
|
|
|
pdmlProtoName_ = "eth";
|
|
|
|
ostProtoId_ = OstProto::Protocol::kMacFieldNumber;
|
|
|
|
|
|
|
|
fieldMap_.insert("eth.dst", OstProto::Mac::kDstMacFieldNumber);
|
|
|
|
fieldMap_.insert("eth.src", OstProto::Mac::kSrcMacFieldNumber);
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlEthProtocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlEthProtocol();
|
|
|
|
}
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
void PdmlEthProtocol::unknownFieldHandler(QString name, int pos, int size,
|
2011-02-18 12:02:57 -06:00
|
|
|
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
|
|
|
if (name == "eth.type")
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = stream->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kEth2FieldNumber);
|
|
|
|
|
|
|
|
OstProto::Eth2 *eth2 = proto->MutableExtension(OstProto::eth2);
|
|
|
|
|
|
|
|
bool isOk;
|
2011-02-18 12:02:57 -06:00
|
|
|
eth2->set_type(attributes.value("value").toString().toUInt(&isOk, kBaseHex));
|
2011-01-30 06:08:03 -06:00
|
|
|
eth2->set_is_override_type(true);
|
|
|
|
}
|
2011-03-06 07:11:08 -06:00
|
|
|
else if (name == "eth.len")
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = stream->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kDot3FieldNumber);
|
|
|
|
|
|
|
|
OstProto::Dot3 *dot3 = proto->MutableExtension(OstProto::dot3);
|
|
|
|
|
|
|
|
bool isOk;
|
|
|
|
dot3->set_length(attributes.value("value").toString().toUInt(&isOk, kBaseHex));
|
|
|
|
dot3->set_is_override_length(true);
|
|
|
|
}
|
|
|
|
else if (name == "eth.trailer")
|
|
|
|
{
|
|
|
|
QByteArray trailer = QByteArray::fromHex(
|
|
|
|
attributes.value("value").toString().toUtf8());
|
|
|
|
|
|
|
|
stream->mutable_core()->mutable_name()->append(trailer.constData(),
|
|
|
|
trailer.size());
|
|
|
|
}
|
|
|
|
else if ((name == "eth.fcs") ||
|
|
|
|
attributes.value("show").toString().startsWith("Frame check sequence"))
|
|
|
|
{
|
|
|
|
QByteArray trailer = QByteArray::fromHex(
|
|
|
|
attributes.value("value").toString().toUtf8());
|
|
|
|
|
|
|
|
stream->mutable_core()->mutable_name()->append(trailer.constData(),
|
|
|
|
trailer.size());
|
|
|
|
}
|
2011-01-30 06:08:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlIp4Protocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlIp4Protocol::PdmlIp4Protocol()
|
|
|
|
{
|
|
|
|
pdmlProtoName_ = "ip";
|
|
|
|
ostProtoId_ = OstProto::Protocol::kIp4FieldNumber;
|
|
|
|
|
|
|
|
fieldMap_.insert("ip.version", 5);
|
|
|
|
fieldMap_.insert("ip.dsfield", 6);
|
|
|
|
fieldMap_.insert("ip.len", 7);
|
|
|
|
fieldMap_.insert("ip.id", 8);
|
|
|
|
//fieldMap_.insert("ip.flags", 9);
|
|
|
|
fieldMap_.insert("ip.frag_offset", 10);
|
|
|
|
fieldMap_.insert("ip.ttl", 11);
|
|
|
|
fieldMap_.insert("ip.proto", 12);
|
|
|
|
fieldMap_.insert("ip.checksum", 13);
|
|
|
|
fieldMap_.insert("ip.src", 14);
|
|
|
|
fieldMap_.insert("ip.dst", 18);
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlIp4Protocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlIp4Protocol();
|
|
|
|
}
|
|
|
|
|
2011-01-30 06:08:03 -06:00
|
|
|
void PdmlIp4Protocol::unknownFieldHandler(QString name, int pos, int size,
|
2011-02-18 12:02:57 -06:00
|
|
|
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
|
|
|
bool isOk;
|
|
|
|
|
2011-03-06 07:11:08 -06:00
|
|
|
if ((name == "ip.options") ||
|
|
|
|
attributes.value("show").toString().startsWith("Options"))
|
|
|
|
{
|
|
|
|
options_ = QByteArray::fromHex(
|
|
|
|
attributes.value("value").toString().toUtf8());
|
|
|
|
}
|
|
|
|
else if (name == "ip.flags")
|
2011-01-30 06:08:03 -06:00
|
|
|
{
|
|
|
|
OstProto::Ip4 *ip4 = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::ip4);
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
ip4->set_flags(attributes.value("value").toString().toUInt(&isOk, kBaseHex) >> 5);
|
2011-01-30 06:08:03 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlIp4Protocol::postProtocolHandler(OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
OstProto::Ip4 *ip4 = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::ip4);
|
|
|
|
|
|
|
|
ip4->set_is_override_ver(true); // FIXME
|
|
|
|
ip4->set_is_override_hdrlen(true); // FIXME
|
|
|
|
ip4->set_is_override_totlen(true); // FIXME
|
|
|
|
ip4->set_is_override_proto(true); // FIXME
|
|
|
|
ip4->set_is_override_cksum(true); // FIXME
|
2011-03-06 07:11:08 -06:00
|
|
|
|
|
|
|
if (options_.size())
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = stream->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kHexDumpFieldNumber);
|
|
|
|
|
|
|
|
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
|
|
|
|
|
|
|
|
hexDump->mutable_content()->append(options_.constData(),
|
|
|
|
options_.size());
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
options_.resize(0);
|
|
|
|
}
|
2011-01-30 06:08:03 -06:00
|
|
|
}
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlIp6Protocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlIp6Protocol::PdmlIp6Protocol()
|
|
|
|
{
|
|
|
|
pdmlProtoName_ = "ipv6";
|
|
|
|
ostProtoId_ = OstProto::Protocol::kIp6FieldNumber;
|
|
|
|
|
|
|
|
fieldMap_.insert("ipv6.version", OstProto::Ip6::kVersionFieldNumber);
|
|
|
|
fieldMap_.insert("ipv6.class", OstProto::Ip6::kTrafficClassFieldNumber);
|
|
|
|
fieldMap_.insert("ipv6.flow", OstProto::Ip6::kFlowLabelFieldNumber);
|
|
|
|
fieldMap_.insert("ipv6.plen", OstProto::Ip6::kPayloadLengthFieldNumber);
|
|
|
|
fieldMap_.insert("ipv6.nxt", OstProto::Ip6::kNextHeaderFieldNumber);
|
|
|
|
fieldMap_.insert("ipv6.hlim", OstProto::Ip6::kHopLimitFieldNumber);
|
|
|
|
|
|
|
|
// ipv6.src and ipv6.dst handled as unknown fields
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlIp6Protocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlIp6Protocol();
|
|
|
|
}
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
void PdmlIp6Protocol::unknownFieldHandler(QString name, int pos, int size,
|
2011-02-18 12:02:57 -06:00
|
|
|
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
2011-02-10 12:00:58 -06:00
|
|
|
{
|
|
|
|
bool isOk;
|
|
|
|
|
|
|
|
if (name == "ipv6.src")
|
|
|
|
{
|
|
|
|
OstProto::Ip6 *ip6 = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
|
2011-02-18 12:02:57 -06:00
|
|
|
QString addrHexStr = attributes.value("value").toString();
|
2011-02-10 12:00:58 -06:00
|
|
|
|
|
|
|
ip6->set_src_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex));
|
|
|
|
ip6->set_src_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex));
|
|
|
|
}
|
|
|
|
else if (name == "ipv6.dst")
|
|
|
|
{
|
|
|
|
OstProto::Ip6 *ip6 = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
|
2011-02-18 12:02:57 -06:00
|
|
|
QString addrHexStr = attributes.value("value").toString();
|
2011-02-10 12:00:58 -06:00
|
|
|
|
|
|
|
ip6->set_dst_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex));
|
|
|
|
ip6->set_dst_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlIp6Protocol::postProtocolHandler(OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
OstProto::Ip6 *ip6 = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
|
|
|
|
|
|
|
|
ip6->set_is_override_version(true); // FIXME
|
|
|
|
ip6->set_is_override_payload_length(true); // FIXME
|
|
|
|
ip6->set_is_override_next_header(true); // FIXME
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
// PdmlTcpProtocol //
|
|
|
|
// ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
PdmlTcpProtocol::PdmlTcpProtocol()
|
|
|
|
{
|
|
|
|
pdmlProtoName_ = "tcp";
|
|
|
|
ostProtoId_ = OstProto::Protocol::kTcpFieldNumber;
|
|
|
|
|
|
|
|
fieldMap_.insert("tcp.srcport", OstProto::Tcp::kSrcPortFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.dstport", OstProto::Tcp::kDstPortFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.seq", OstProto::Tcp::kSeqNumFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.ack", OstProto::Tcp::kAckNumFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.hdr_len", OstProto::Tcp::kHdrlenRsvdFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.flags", OstProto::Tcp::kFlagsFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.window_size", OstProto::Tcp::kWindowFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.checksum", OstProto::Tcp::kCksumFieldNumber);
|
|
|
|
fieldMap_.insert("tcp.urgent_pointer", OstProto::Tcp::kUrgPtrFieldNumber);
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
PdmlDefaultProtocol* PdmlTcpProtocol::createInstance()
|
|
|
|
{
|
|
|
|
return new PdmlTcpProtocol();
|
|
|
|
}
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
void PdmlTcpProtocol::unknownFieldHandler(QString name, int pos, int size,
|
2011-02-18 12:02:57 -06:00
|
|
|
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
|
2011-02-10 12:00:58 -06:00
|
|
|
{
|
|
|
|
if (name == "tcp.options")
|
2011-02-18 12:02:57 -06:00
|
|
|
options_ = QByteArray::fromHex(attributes.value("value").toString().toUtf8());
|
2011-03-12 03:46:27 -06:00
|
|
|
else if (name == "")
|
2011-02-10 12:00:58 -06:00
|
|
|
{
|
2011-03-12 03:46:27 -06:00
|
|
|
if (attributes.value("show").toString().startsWith("TCP segment data"))
|
|
|
|
{
|
|
|
|
segmentData_ = QByteArray::fromHex(attributes.value("value").toString().toUtf8());
|
|
|
|
stream->mutable_core()->mutable_name()->insert(0,
|
|
|
|
segmentData_.constData(), segmentData_.size());
|
|
|
|
}
|
|
|
|
else if (attributes.value("show").toString().startsWith("Acknowledgement number"))
|
|
|
|
{
|
|
|
|
bool isOk;
|
|
|
|
OstProto::Tcp *tcp = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::tcp);
|
|
|
|
|
|
|
|
tcp->set_ack_num(attributes.value("value").toString().toUInt(&isOk, kBaseHex));
|
|
|
|
}
|
2011-02-10 12:00:58 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PdmlTcpProtocol::postProtocolHandler(OstProto::Stream *stream)
|
|
|
|
{
|
|
|
|
OstProto::Tcp *tcp = stream->mutable_protocol(
|
|
|
|
stream->protocol_size()-1)->MutableExtension(OstProto::tcp);
|
|
|
|
|
2011-02-18 12:02:57 -06:00
|
|
|
qDebug("Tcp: post\n");
|
|
|
|
|
2011-02-10 12:00:58 -06:00
|
|
|
tcp->set_is_override_src_port(true); // FIXME
|
|
|
|
tcp->set_is_override_dst_port(true); // FIXME
|
|
|
|
tcp->set_is_override_hdrlen(true); // FIXME
|
|
|
|
tcp->set_is_override_cksum(true); // FIXME
|
|
|
|
|
|
|
|
if (options_.size())
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = stream->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kHexDumpFieldNumber);
|
|
|
|
|
|
|
|
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
|
|
|
|
|
|
|
|
hexDump->mutable_content()->append(options_.constData(),
|
|
|
|
options_.size());
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
options_.resize(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (segmentData_.size())
|
|
|
|
{
|
|
|
|
OstProto::Protocol *proto = stream->add_protocol();
|
|
|
|
|
|
|
|
proto->mutable_protocol_id()->set_id(
|
|
|
|
OstProto::Protocol::kHexDumpFieldNumber);
|
|
|
|
|
|
|
|
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
|
|
|
|
|
|
|
|
hexDump->mutable_content()->append(segmentData_.constData(),
|
|
|
|
segmentData_.size());
|
|
|
|
hexDump->set_pad_until_end(false);
|
|
|
|
segmentData_.resize(0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|