This commit is contained in:
Srivats P. 2011-02-18 23:32:57 +05:30
parent a70a6c5350
commit 5ab89bba29
8 changed files with 871 additions and 43 deletions

View File

@ -31,3 +31,5 @@ version.cpp
# ctags
tags
pcaps\*

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "port.h"
#include "fileformat.h"
#include "pdmlfileformat.h"
#include "pcapfileformat.h"
#include <QApplication>
#include <QVariant>
@ -229,7 +229,7 @@ bool Port::openStreams(QString fileName, bool append, QString &error)
OstProto::StreamConfigList streams;
//if (!fileFormat.openStreams(fileName, streams, error))
if (!pdmlFileFormat.openStreams(fileName, streams, error))
if (!pcapFileFormat.openStreams(fileName, streams, error))
goto _fail;
if (!append)
@ -262,5 +262,6 @@ bool Port::saveStreams(QString fileName, QString &error)
mStreams[i]->protoDataCopyInto(*s);
}
return fileFormat.saveStreams(streams, fileName, error);
//return fileFormat.saveStreams(streams, fileName, error);
return pcapFileFormat.saveStreams(streams, fileName, error);
}

View File

@ -58,6 +58,7 @@ HEADERS += \
abstractprotocol.h \
comboprotocol.h \
fileformat.h \
pcapfileformat.h \
pdmlfileformat.h \
pdml_p.h \
protocolmanager.h \
@ -98,6 +99,7 @@ SOURCES += \
abstractprotocol.cpp \
crc32c.cpp \
fileformat.cpp \
pcapfileformat.cpp \
pdmlfileformat.cpp \
pdml_p.cpp \
protocolmanager.cpp \

252
common/pcapfileformat.cpp Normal file
View File

@ -0,0 +1,252 @@
/*
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 "pcapfileformat.h"
#include "streambase.h"
#include "hexdump.pb.h"
#include <QDataStream>
#include <QFile>
#include <QtGlobal>
static inline quint32 swap32(quint32 val)
{
return (((val >> 24) && 0x000000FF) |
((val >> 16) && 0x0000FF00) |
((val << 16) && 0x00FF0000) |
((val << 24) && 0xFF000000));
}
static inline quint16 swap16(quint16 val)
{
return (((val >> 8) && 0x00FF) |
((val << 8) && 0xFF00));
}
typedef struct {
quint32 magicNumber; /* magic number */
quint16 versionMajor; /* major version number */
quint16 versionMinor; /* minor version number */
qint32 thisZone; /* GMT to local correction */
quint32 sigfigs; /* accuracy of timestamps */
quint32 snapLen; /* max length of captured packets, in octets */
quint32 network; /* data link type */
} PcapFileHeader;
const quint32 kPcapFileMagic = 0xa1b2c3d4;
const quint32 kPcapFileMagicSwapped = 0xd4c3b2a1;
const quint16 kPcapFileVersionMajor = 2;
const quint16 kPcapFileVersionMinor = 4;
const quint32 kMaxSnapLen = 65535;
typedef struct {
quint32 tsSec; /* timestamp seconds */
quint32 tsUsec; /* timestamp microseconds */
quint32 inclLen; /* number of octets of packet saved in file */
quint32 origLen; /* actual length of packet */
} PcapPacketHeader;
PcapFileFormat pcapFileFormat;
PcapFileFormat::PcapFileFormat()
{
}
PcapFileFormat::~PcapFileFormat()
{
}
bool PcapFileFormat::openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error)
{
bool isOk = false;
QFile file(fileName);
QDataStream fd;
quint32 magic;
PcapFileHeader fileHdr;
PcapPacketHeader pktHdr;
quint32 len;
int pktCount = 1;
QByteArray pktBuf;
if (!file.open(QIODevice::ReadOnly))
goto _err_open;
if (file.size() < sizeof(fileHdr))
goto _err_truncated;
fd.setDevice(&file);
fd >> magic;
if (magic == kPcapFileMagicSwapped)
{
// Toggle Byte order
if (fd.byteOrder() == QDataStream::BigEndian)
fd.setByteOrder(QDataStream::LittleEndian);
else
fd.setByteOrder(QDataStream::BigEndian);
}
else if (magic != kPcapFileMagic)
goto _err_bad_magic;
fd >> fileHdr.versionMajor;
fd >> fileHdr.versionMinor;
fd >> fileHdr.thisZone;
fd >> fileHdr.sigfigs;
fd >> fileHdr.snapLen;
fd >> fileHdr.network;
if ((fileHdr.versionMajor != kPcapFileVersionMajor) ||
(fileHdr.versionMinor != kPcapFileVersionMinor))
goto _err_unsupported_version;
// TODO: what do we do about non-ethernet networks?
pktBuf.resize(fileHdr.snapLen);
while (!fd.atEnd())
{
OstProto::Stream *stream = streams.add_stream();
OstProto::Protocol *proto = stream->add_protocol();
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
stream->mutable_stream_id()->set_id(pktCount);
stream->mutable_core()->set_is_enabled(true);
proto->mutable_protocol_id()->set_id(
OstProto::Protocol::kHexDumpFieldNumber);
// read PcapPacketHeader
fd >> pktHdr.tsSec;
fd >> pktHdr.tsUsec;
fd >> pktHdr.inclLen;
fd >> pktHdr.origLen;
// TODO: chk fd.status()
// validations on inclLen <= origLen && inclLen <= snapLen
Q_ASSERT(pktHdr.inclLen <= fileHdr.snapLen); // TODO: convert to if
// read Pkt contents
len = fd.readRawData(pktBuf.data(), pktHdr.inclLen); // TODO: use while?
Q_ASSERT(len == pktHdr.inclLen); // TODO: remove assert
hexDump->set_content(pktBuf.data(), pktHdr.inclLen);
hexDump->set_pad_until_end(false);
stream->mutable_core()->set_frame_len(pktHdr.inclLen+4); // FCS
pktCount++;
}
isOk = true;
goto _exit;
_err_unsupported_version:
error = QString(tr("%1 is in PCAP version %2.%3 format which is "
"not supported - Sorry!"))
.arg(fileName).arg(fileHdr.versionMajor).arg(fileHdr.versionMinor);
goto _exit;
_err_bad_magic:
error = QString(tr("%1 is not a valid PCAP file")).arg(fileName);
goto _exit;
_err_truncated:
error = QString(tr("%1 is too short")).arg(fileName);
goto _exit;
_err_open:
error = QString(tr("Unable to open file: %1")).arg(fileName);
goto _exit;
_exit:
return isOk;
}
bool PcapFileFormat::saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error)
{
bool isOk = false;
QFile file(fileName);
QDataStream fd;
PcapFileHeader fileHdr;
PcapPacketHeader pktHdr;
QByteArray pktBuf;
if (!file.open(QIODevice::WriteOnly))
goto _err_open;
fd.setDevice(&file);
fileHdr.magicNumber = kPcapFileMagic;
fileHdr.versionMajor = kPcapFileVersionMajor;
fileHdr.versionMinor = kPcapFileVersionMinor;
fileHdr.thisZone = 0;
fileHdr.sigfigs = 0;
fileHdr.snapLen = kMaxSnapLen;
fileHdr.network = 1; // Ethernet; FIXME: Hardcoding
fd << fileHdr.magicNumber;
fd << fileHdr.versionMajor;
fd << fileHdr.versionMinor;
fd << fileHdr.thisZone;
fd << fileHdr.sigfigs;
fd << fileHdr.snapLen;
fd << fileHdr.network;
pktBuf.resize(kMaxSnapLen);
for (int i = 0; i < streams.stream_size(); i++)
{
StreamBase s;
s.setId(i);
s.protoDataCopyFrom(streams.stream(i));
// TODO: expand frameIndex for each stream
s.frameValue((uchar*)pktBuf.data(), pktBuf.size(), 0);
// TODO: write actual timing!?!?
pktHdr.tsSec = 0;
pktHdr.tsUsec = 0;
pktHdr.inclLen = pktHdr.origLen = s.frameLen() - 4; // FCS; FIXME: Hardcoding
if (pktHdr.inclLen > fileHdr.snapLen)
pktHdr.inclLen = fileHdr.snapLen;
fd << pktHdr.tsSec;
fd << pktHdr.tsUsec;
fd << pktHdr.inclLen;
fd << pktHdr.origLen;
fd.writeRawData(pktBuf.data(), pktHdr.inclLen);
}
file.close();
isOk = true;
goto _exit;
_err_open:
error = QString(tr("Unable to open file: %1")).arg(fileName);
goto _exit;
_exit:
return isOk;
}

42
common/pcapfileformat.h Normal file
View File

@ -0,0 +1,42 @@
/*
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/>
*/
#ifndef _PCAP_FILE_FORMAT_H
#define _PCAP_FILE_FORMAT_H
#include "protocol.pb.h"
#include <QObject>
class PcapFileFormat : public QObject
{
Q_OBJECT
public:
PcapFileFormat();
~PcapFileFormat();
bool openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error);
bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error);
};
extern PcapFileFormat pcapFileFormat;
#endif

View File

@ -43,6 +43,11 @@ PdmlDefaultProtocol::~PdmlDefaultProtocol()
{
}
PdmlDefaultProtocol* PdmlDefaultProtocol::createInstance()
{
return new PdmlDefaultProtocol();
}
QString PdmlDefaultProtocol::pdmlProtoName() const
{
return pdmlProtoName_;
@ -64,7 +69,12 @@ int PdmlDefaultProtocol::fieldId(QString name) const
}
void PdmlDefaultProtocol::preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
return; // do nothing!
}
void PdmlDefaultProtocol::prematureEndHandler(int pos, OstProto::Stream *stream)
{
return; // do nothing!
}
@ -75,13 +85,14 @@ void PdmlDefaultProtocol::postProtocolHandler(OstProto::Stream *stream)
}
void PdmlDefaultProtocol::unknownFieldHandler(QString name,
int pos, int size, const QXmlAttributes &attributes,
int pos, int size, const QXmlStreamAttributes &attributes,
OstProto::Stream *stream)
{
return; // do nothing!
}
#if 0
// ---------------------------------------------------------- //
// PdmlParser
// ---------------------------------------------------------- //
@ -328,6 +339,392 @@ bool PdmlParser::fatalError(const QXmlParseException &exception)
.arg(extra));
return false;
}
#endif
// ---------------------------------------------------------- //
// PdmlReader //
// ---------------------------------------------------------- //
PdmlReader::PdmlReader(OstProto::StreamConfigList *streams)
{
streams_ = streams;
factory_.insert("hexdump", PdmlUnknownProtocol::createInstance);
factory_.insert("geninfo", PdmlGenInfoProtocol::createInstance);
factory_.insert("frame", PdmlFrameProtocol::createInstance);
#if 0
factory_.insert("fake-field-wrapper",
new PdmlFakeFieldWrapperProtocol());
#endif
factory_.insert("eth",PdmlEthProtocol::createInstance);
factory_.insert("ip",PdmlIp4Protocol::createInstance);
factory_.insert("ipv6",PdmlIp6Protocol::createInstance);
factory_.insert("tcp",PdmlTcpProtocol::createInstance);
}
PdmlReader::~PdmlReader()
{
}
bool PdmlReader::read(QIODevice *device)
{
setDevice(device);
packetCount_ = 0;
while (!atEnd())
{
readNext();
if (isStartElement())
{
if (name() == "pdml")
readPdml();
else
raiseError("Not a pdml file!");
}
}
return !error();
}
// 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");
packetCount_ = 0;
while (!atEnd())
{
readNext();
if (isEndElement())
break;
if (isStartElement())
{
if (name() == "packet")
readPacket();
else
readUnexpectedElement();
}
}
}
void PdmlReader::readPacket()
{
Q_ASSERT(isStartElement() && name() == "packet");
packetCount_++;
qDebug("packetNum = %d", packetCount_);
// XXX: For now, each packet is converted to a stream
currentStream_ = streams_->add_stream();
currentStream_->mutable_stream_id()->set_id(packetCount_);
currentStream_->mutable_core()->set_is_enabled(true);
while (!atEnd())
{
readNext();
if (isEndElement())
break;
if (isStartElement())
{
if (name() == "proto")
readProto();
else if (name() == "field")
readField(NULL, NULL); // TODO: top level field!!!!
else
readUnexpectedElement();
}
}
if (currentStream_->core().name().size())
{
OstProto::Protocol *proto = currentStream_->add_protocol();
proto->mutable_protocol_id()->set_id(
OstProto::Protocol::kHexDumpFieldNumber);
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
hexDump->set_content(currentStream_->core().name());
hexDump->set_pad_until_end(false);
currentStream_->mutable_core()->set_name("");
}
}
void PdmlReader::readProto()
{
PdmlDefaultProtocol *pdmlProto = NULL;
google::protobuf::Message *pbProto = NULL;
Q_ASSERT(isStartElement() && name() == "proto");
QString protoName = attributes().value("name").toString();
qDebug("proto: %s", protoName.toAscii().constData());
#if 0
if (protoName.isEmpty() || (protoName == "expert"))
{
skipElement();
return;
}
#endif
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);
}
pdmlProto->preProtocolHandler(protoName, attributes(), currentStream_);
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_);
}
readProto();
pdmlProto = NULL;
pbProto = NULL;
}
else if (name() == "field")
{
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);
}
pdmlProto->preProtocolHandler(protoName, attributes(), currentStream_);
}
readField(pdmlProto, pbProto);
}
else
readUnexpectedElement();
}
}
if (pdmlProto)
{
pdmlProto->postProtocolHandler(currentStream_);
freePdmlProtocol(pdmlProto);
}
}
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();
}
}
}
// ---------------------------------------------------------- //
@ -336,22 +733,27 @@ bool PdmlParser::fatalError(const QXmlParseException &exception)
PdmlUnknownProtocol::PdmlUnknownProtocol()
{
pdmlProtoName_ = "OST:HexDump";
pdmlProtoName_ = "";
ostProtoId_ = OstProto::Protocol::kHexDumpFieldNumber;
endPos_ = expPos_ = -1;
}
PdmlDefaultProtocol* PdmlUnknownProtocol::createInstance()
{
return new PdmlUnknownProtocol();
}
void PdmlUnknownProtocol::preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
bool isOk;
int size;
int pos = attributes.value("pos").toUInt(&isOk);
int pos = attributes.value("pos").toString().toUInt(&isOk);
if (!isOk)
goto _skip_pos_size_proc;
size = attributes.value("size").toUInt(&isOk);
size = attributes.value("size").toString().toUInt(&isOk);
if (!isOk)
goto _skip_pos_size_proc;
@ -364,6 +766,11 @@ _skip_pos_size_proc:
hexDump->set_pad_until_end(false);
}
void PdmlUnknownProtocol::prematureEndHandler(int pos, OstProto::Stream *stream)
{
endPos_ = pos;
}
void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream)
{
OstProto::HexDump *hexDump = stream->mutable_protocol(
@ -378,7 +785,7 @@ void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream)
expPos_ += hexVal.size();
}
qDebug("%s: expPos_ = %d, endPos_ = %d\n", __FUNCTION__, expPos_, endPos_);
qDebug(" hexdump: expPos_ = %d, endPos_ = %d\n", expPos_, endPos_);
//Q_ASSERT(expPos_ == endPos_);
hexDump->set_pad_until_end(false);
@ -386,13 +793,13 @@ void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream)
}
void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
qDebug("%s: %s, pos = %d, expPos_ = %d, endPos_ = %d\n",
__PRETTY_FUNCTION__, name.toAscii().constData(),
qDebug(" hexdump: %s, pos = %d, expPos_ = %d, endPos_ = %d\n",
name.toAscii().constData(),
pos, expPos_, endPos_);
// Skipped field? Pad with zero!
@ -407,8 +814,8 @@ void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size,
if ((pos == expPos_) /*&& (pos < endPos_)*/)
{
QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ?
QByteArray::fromHex(attributes.value("value").toUtf8()) :
QByteArray::fromHex(attributes.value("unmaskedvalue").toUtf8());
QByteArray::fromHex(attributes.value("value").toString().toUtf8()) :
QByteArray::fromHex(attributes.value("unmaskedvalue").toString().toUtf8());
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
expPos_ += hexVal.size();
@ -425,8 +832,13 @@ PdmlGenInfoProtocol::PdmlGenInfoProtocol()
pdmlProtoName_ = "geninfo";
}
PdmlDefaultProtocol* PdmlGenInfoProtocol::createInstance()
{
return new PdmlGenInfoProtocol();
}
void PdmlGenInfoProtocol::unknownFieldHandler(QString name, int pos,
int size, const QXmlAttributes &attributes, OstProto::Stream *stream)
int size, const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
stream->mutable_core()->set_frame_len(size+4); // TODO:check FCS
}
@ -440,6 +852,11 @@ PdmlFrameProtocol::PdmlFrameProtocol()
pdmlProtoName_ = "frame";
}
PdmlDefaultProtocol* PdmlFrameProtocol::createInstance()
{
return new PdmlFrameProtocol();
}
#if 1
// ---------------------------------------------------------- //
// PdmlFakeFieldWrapperProtocol //
@ -453,8 +870,13 @@ PdmlFakeFieldWrapperProtocol::PdmlFakeFieldWrapperProtocol()
expPos_ = -1;
}
PdmlDefaultProtocol* PdmlFakeFieldWrapperProtocol::createInstance()
{
return new PdmlFakeFieldWrapperProtocol();
}
void PdmlFakeFieldWrapperProtocol::preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
expPos_ = 0;
OstProto::HexDump *hexDump = stream->mutable_protocol(
@ -474,7 +896,7 @@ void PdmlFakeFieldWrapperProtocol::postProtocolHandler(OstProto::Stream *stream)
}
void PdmlFakeFieldWrapperProtocol::unknownFieldHandler(QString name, int pos,
int size, const QXmlAttributes &attributes, OstProto::Stream *stream)
int size, const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
@ -484,8 +906,8 @@ void PdmlFakeFieldWrapperProtocol::unknownFieldHandler(QString name, int pos,
!attributes.value("value").isEmpty()))
{
QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ?
QByteArray::fromHex(attributes.value("value").toUtf8()) :
QByteArray::fromHex(attributes.value("unmaskedvalue").toUtf8());
QByteArray::fromHex(attributes.value("value").toString().toUtf8()) :
QByteArray::fromHex(attributes.value("unmaskedvalue").toString().toUtf8());
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
expPos_ += hexVal.size();
@ -506,8 +928,13 @@ PdmlEthProtocol::PdmlEthProtocol()
fieldMap_.insert("eth.src", OstProto::Mac::kSrcMacFieldNumber);
}
PdmlDefaultProtocol* PdmlEthProtocol::createInstance()
{
return new PdmlEthProtocol();
}
void PdmlEthProtocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
if (name == "eth.type")
{
@ -519,7 +946,7 @@ void PdmlEthProtocol::unknownFieldHandler(QString name, int pos, int size,
OstProto::Eth2 *eth2 = proto->MutableExtension(OstProto::eth2);
bool isOk;
eth2->set_type(attributes.value("value").toUInt(&isOk, kBaseHex));
eth2->set_type(attributes.value("value").toString().toUInt(&isOk, kBaseHex));
eth2->set_is_override_type(true);
}
}
@ -547,8 +974,13 @@ PdmlIp4Protocol::PdmlIp4Protocol()
fieldMap_.insert("ip.dst", 18);
}
PdmlDefaultProtocol* PdmlIp4Protocol::createInstance()
{
return new PdmlIp4Protocol();
}
void PdmlIp4Protocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
bool isOk;
@ -557,7 +989,7 @@ void PdmlIp4Protocol::unknownFieldHandler(QString name, int pos, int size,
OstProto::Ip4 *ip4 = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::ip4);
ip4->set_flags(attributes.value("value").toUInt(&isOk, kBaseHex) >> 5);
ip4->set_flags(attributes.value("value").toString().toUInt(&isOk, kBaseHex) >> 5);
}
}
@ -592,8 +1024,13 @@ PdmlIp6Protocol::PdmlIp6Protocol()
// ipv6.src and ipv6.dst handled as unknown fields
}
PdmlDefaultProtocol* PdmlIp6Protocol::createInstance()
{
return new PdmlIp6Protocol();
}
void PdmlIp6Protocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
bool isOk;
@ -601,7 +1038,7 @@ void PdmlIp6Protocol::unknownFieldHandler(QString name, int pos, int size,
{
OstProto::Ip6 *ip6 = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
QString addrHexStr = attributes.value("value");
QString addrHexStr = attributes.value("value").toString();
ip6->set_src_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex));
ip6->set_src_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex));
@ -610,7 +1047,7 @@ void PdmlIp6Protocol::unknownFieldHandler(QString name, int pos, int size,
{
OstProto::Ip6 *ip6 = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
QString addrHexStr = attributes.value("value");
QString addrHexStr = attributes.value("value").toString();
ip6->set_dst_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex));
ip6->set_dst_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex));
@ -647,15 +1084,20 @@ PdmlTcpProtocol::PdmlTcpProtocol()
fieldMap_.insert("tcp.urgent_pointer", OstProto::Tcp::kUrgPtrFieldNumber);
}
PdmlDefaultProtocol* PdmlTcpProtocol::createInstance()
{
return new PdmlTcpProtocol();
}
void PdmlTcpProtocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream)
const QXmlStreamAttributes &attributes, OstProto::Stream *stream)
{
if (name == "tcp.options")
options_ = QByteArray::fromHex(attributes.value("value").toUtf8());
options_ = QByteArray::fromHex(attributes.value("value").toString().toUtf8());
else if (name == ""
&& attributes.value("show").startsWith("TCP segment data"))
&& attributes.value("show").toString().startsWith("TCP segment data"))
{
segmentData_ = QByteArray::fromHex(attributes.value("value").toUtf8());
segmentData_ = QByteArray::fromHex(attributes.value("value").toString().toUtf8());
stream->mutable_core()->mutable_name()->append(segmentData_.constData(),
segmentData_.size());
}
@ -666,6 +1108,8 @@ void PdmlTcpProtocol::postProtocolHandler(OstProto::Stream *stream)
OstProto::Tcp *tcp = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::tcp);
qDebug("Tcp: post\n");
tcp->set_is_override_src_port(true); // FIXME
tcp->set_is_override_dst_port(true); // FIXME
tcp->set_is_override_hdrlen(true); // FIXME

View File

@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include <QObject>
#include <QString>
#include <QXmlDefaultHandler>
#include <QXmlStreamReader>
// TODO: add const where possible
@ -35,19 +36,22 @@ class QXmlInputSource;
class PdmlDefaultProtocol
{
public:
PdmlDefaultProtocol();
PdmlDefaultProtocol(); // TODO: make private
virtual ~PdmlDefaultProtocol();
static PdmlDefaultProtocol* createInstance();
QString pdmlProtoName() const;
int ostProtoId() const;
bool hasField(QString name) const;
int fieldId(QString name) const;
virtual void preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
virtual void prematureEndHandler(int pos, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
protected:
QString pdmlProtoName_; // TODO: needed? duplicated in protocolMap_
@ -55,6 +59,7 @@ protected:
QMap<QString, int> fieldMap_;
};
#if 0
class PdmlParser : public QXmlDefaultHandler
{
public:
@ -83,17 +88,53 @@ private:
OstProto::Stream *currentStream_;
google::protobuf::Message *currentProtocolMsg_;
};
#endif
class PdmlReader : public QXmlStreamReader
{
public:
PdmlReader(OstProto::StreamConfigList *streams);
~PdmlReader();
bool read(QIODevice *device);
private:
PdmlDefaultProtocol* allocPdmlProtocol(QString protoName);
void freePdmlProtocol(PdmlDefaultProtocol *proto);
bool isDontCareProto();
void readPdml();
void skipElement();
void readUnexpectedElement();
void readPacket();
void readProto();
void readField(PdmlDefaultProtocol *pdmlProto,
google::protobuf::Message *pbProto);
typedef PdmlDefaultProtocol* (*FactoryMethod)();
QMap<QString, FactoryMethod> factory_;
OstProto::StreamConfigList *streams_;
int packetCount_;
OstProto::Stream *currentStream_;
//PdmlDefaultProtocol *currentPdmlProtocol_;
//google::protobuf::Message *currentProtocolMsg_;
};
class PdmlUnknownProtocol : public PdmlDefaultProtocol
{
public:
PdmlUnknownProtocol();
static PdmlDefaultProtocol* createInstance();
virtual void preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
virtual void prematureEndHandler(int pos, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
private:
int endPos_;
int expPos_;
@ -104,14 +145,18 @@ class PdmlGenInfoProtocol : public PdmlDefaultProtocol
public:
PdmlGenInfoProtocol();
static PdmlDefaultProtocol* createInstance();
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
};
class PdmlFrameProtocol : public PdmlDefaultProtocol
{
public:
PdmlFrameProtocol();
static PdmlDefaultProtocol* createInstance();
};
#if 1
@ -120,11 +165,13 @@ class PdmlFakeFieldWrapperProtocol : public PdmlDefaultProtocol
public:
PdmlFakeFieldWrapperProtocol();
static PdmlDefaultProtocol* createInstance();
virtual void preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
private:
int expPos_;
};
@ -135,16 +182,21 @@ class PdmlEthProtocol : public PdmlDefaultProtocol
public:
PdmlEthProtocol();
static PdmlDefaultProtocol* createInstance();
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
};
class PdmlIp4Protocol : public PdmlDefaultProtocol
{
public:
PdmlIp4Protocol();
static PdmlDefaultProtocol* createInstance();
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
};
@ -152,8 +204,11 @@ class PdmlIp6Protocol : public PdmlDefaultProtocol
{
public:
PdmlIp6Protocol();
static PdmlDefaultProtocol* createInstance();
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
};
@ -161,8 +216,11 @@ class PdmlTcpProtocol : public PdmlDefaultProtocol
{
public:
PdmlTcpProtocol();
static PdmlDefaultProtocol* createInstance();
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
const QXmlStreamAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
private:
QByteArray options_;

View File

@ -30,6 +30,7 @@ PdmlFileFormat::~PdmlFileFormat()
{
}
#if 0
bool PdmlFileFormat::openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error)
{
@ -61,6 +62,32 @@ _exit:
return isOk;
}
#else
bool PdmlFileFormat::openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error)
{
bool isOk = false;
QFile file(fileName);
PdmlReader *reader = new PdmlReader(&streams);
if (!file.open(QIODevice::ReadOnly))
goto _open_fail;
// TODO: fill in error string
isOk = reader->read(&file);
goto _exit;
_open_fail:
isOk = false;
_exit:
delete reader;
return isOk;
}
#endif
bool PdmlFileFormat::saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error)