This commit is contained in:
Srivats P. 2011-02-23 21:28:32 +05:30
parent 16d85a338a
commit b7ce0a6faf
8 changed files with 258 additions and 28 deletions

View File

@ -34,6 +34,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
const int kBaseHex = 16;
static PdmlReader *gPdmlReader = NULL;
PdmlDefaultProtocol::PdmlDefaultProtocol()
{
ostProtoId_ = -1;
@ -346,6 +348,8 @@ bool PdmlParser::fatalError(const QXmlParseException &exception)
// ---------------------------------------------------------- //
PdmlReader::PdmlReader(OstProto::StreamConfigList *streams)
{
gPdmlReader = this;
pass_ = 0;
streams_ = streams;
factory_.insert("hexdump", PdmlUnknownProtocol::createInstance);
@ -370,6 +374,28 @@ bool PdmlReader::read(QIODevice *device)
setDevice(device);
packetCount_ = 0;
// 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);
// 2nd pass - actual processing
pass_ = 2;
qDebug("PASS %d\n", pass_);
while (!atEnd())
{
readNext();
@ -451,7 +477,7 @@ void PdmlReader::readPdml()
{
Q_ASSERT(isStartElement() && name() == "pdml");
packetCount_ = 0;
packetCount_ = 1;
while (!atEnd())
{
@ -462,19 +488,137 @@ void PdmlReader::readPdml()
if (isStartElement())
{
if (name() == "packet")
readPacket();
{
if (pass_ == 1)
readPacketPass1();
else if (pass_ == 2)
readPacket();
else
Q_ASSERT(false); // unreachable!
}
else
readUnexpectedElement();
}
}
}
void PdmlReader::readPacketPass1()
{
Q_ASSERT(isStartElement() && name() == "packet");
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();
}
}
packetCount_++;
}
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();
}
}
}
void PdmlReader::readPacket()
{
Q_ASSERT(isStartElement() && name() == "packet");
//Q_ASSERT(isStartElement() && name() == "packet");
packetCount_++;
qDebug("packetNum = %d", packetCount_);
qDebug("%s: packetNum = %d", __FUNCTION__, packetCount_);
// XXX: For now, each packet is converted to a stream
currentStream_ = streams_->add_stream();
@ -512,8 +656,9 @@ void PdmlReader::readPacket()
hexDump->set_pad_until_end(false);
currentStream_->mutable_core()->set_name("");
}
}
packetCount_++;
}
void PdmlReader::readProto()
{
@ -805,10 +950,22 @@ void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size,
// Skipped field? Pad with zero!
if ((pos > expPos_) && (expPos_ < endPos_))
{
QByteArray hexVal(pos - expPos_, char(0));
PdmlReader::Fragment f;
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
expPos_ += hexVal.size();
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
{
QByteArray hexVal(pos - expPos_, char(0));
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
expPos_ += hexVal.size();
}
}
if ((pos == expPos_) /*&& (pos < endPos_)*/)

View File

@ -90,8 +90,10 @@ private:
};
#endif
class PdmlUnknownProtocol;
class PdmlReader : public QXmlStreamReader
{
friend class PdmlUnknownProtocol;
public:
PdmlReader(OstProto::StreamConfigList *streams);
~PdmlReader();
@ -106,18 +108,48 @@ private:
void readPdml();
void skipElement();
void readUnexpectedElement();
void readPacketPass1();
void readProtoPass1();
void readFieldPass1();
void readPacket();
void readProto();
void readField(PdmlDefaultProtocol *pdmlProto,
google::protobuf::Message *pbProto);
typedef PdmlDefaultProtocol* (*FactoryMethod)();
#if 0
class PacketFragment // TODO: find a better name!
{
public:
private:
typedef struct
{
int pos;
int size;
QByteArray value;
} Fragment;
QList<Fragment>
};
#endif
typedef struct
{
int pos;
int size;
QByteArray value;
} Fragment;
QMap<QString, FactoryMethod> factory_;
OstProto::StreamConfigList *streams_;
int pass_;
int packetCount_;
OstProto::Stream *currentStream_;
QList<Fragment> pktFragments_;
//PdmlDefaultProtocol *currentPdmlProtocol_;
//google::protobuf::Message *currentProtocolMsg_;
};

View File

@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
AbstractPort::AbstractPort(int id, const char *device)
{
isUsable_ = true;
data_.mutable_port_id()->set_id(id);
data_.set_name(device);

View File

@ -47,6 +47,8 @@ public:
AbstractPort(int id, const char *device);
virtual ~AbstractPort();
bool isUsable() { return isUsable_; }
virtual void init();
int id() { return data_.port_id().id(); }
@ -86,6 +88,7 @@ public:
void resetStats() { epochStats_ = stats_; }
protected:
bool isUsable_;
OstProto::Port data_;
OstProto::LinkState linkState_;

View File

@ -35,6 +35,9 @@ PcapPort::PcapPort(int id, const char *device)
transmitter_ = new PortTransmitter(device);
capturer_ = new PortCapturer(device);
if (!monitorRx_->handle() || !monitorTx_->handle())
isUsable_ = false;
if (!deviceList_)
{
char errbuf[PCAP_ERRBUF_SIZE];
@ -106,16 +109,27 @@ PcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
AbstractPort::PortStats *stats)
{
int ret;
char errbuf[PCAP_ERRBUF_SIZE];
int flag = PCAP_OPENFLAG_PROMISCUOUS;
char errbuf[PCAP_ERRBUF_SIZE] = "";
direction_ = direction;
isDirectional_ = true;
stats_ = stats;
handle_ = pcap_open_live(device, 64 /* FIXME */, PCAP_OPENFLAG_PROMISCUOUS,
_retry:
handle_ = pcap_open_live(device, 64 /* FIXME */, flag,
1000 /* ms */, errbuf);
if (handle_ == NULL)
goto _open_error;
{
if (flag && QString(errbuf).contains("promiscuous"))
{
qDebug("%s:can't set promiscuous mode, trying non-promisc", device);
flag = 0;
goto _retry;
}
else
goto _open_error;
}
#ifdef Q_OS_WIN32
// pcap_setdirection() API is not supported in Windows.
// NOTE: WinPcap 4.1.1 and above exports a dummy API that returns -1
@ -149,7 +163,7 @@ _set_direction_error:
return;
_open_error:
qDebug("Error opening port %s: %s\n", device, pcap_geterr(handle_));
qDebug("%s: Error opening port %s: %s\n", __FUNCTION__, device, errbuf);
}
void PcapPort::PortMonitor::run()
@ -201,7 +215,7 @@ void PcapPort::PortMonitor::run()
PcapPort::PortTransmitter::PortTransmitter(const char *device)
{
char errbuf[PCAP_ERRBUF_SIZE];
char errbuf[PCAP_ERRBUF_SIZE] = "";
#ifdef Q_OS_WIN32
LARGE_INTEGER freq;
@ -216,8 +230,7 @@ PcapPort::PortTransmitter::PortTransmitter(const char *device)
stop_ = false;
stats_ = new AbstractPort::PortStats;
usingInternalStats_ = true;
handle_ = pcap_open_live(device, 64 /* FIXME */, PCAP_OPENFLAG_PROMISCUOUS,
1000 /* ms */, errbuf);
handle_ = pcap_open_live(device, 64 /* FIXME */, 0, 1000 /* ms */, errbuf);
if (handle_ == NULL)
goto _open_error;
@ -227,7 +240,7 @@ PcapPort::PortTransmitter::PortTransmitter(const char *device)
return;
_open_error:
qDebug("Error opening port %s: %s\n", device, pcap_geterr(handle_));
qDebug("%s: Error opening port %s: %s\n", __FUNCTION__, device, errbuf);
usingInternalHandle_ = false;
}
@ -434,7 +447,8 @@ PcapPort::PortCapturer::~PortCapturer()
void PcapPort::PortCapturer::run()
{
char errbuf[PCAP_ERRBUF_SIZE];
int flag = PCAP_OPENFLAG_PROMISCUOUS;
char errbuf[PCAP_ERRBUF_SIZE] = "";
qDebug("In %s", __PRETTY_FUNCTION__);
@ -443,14 +457,25 @@ void PcapPort::PortCapturer::run()
qWarning("temp cap file is not open");
return;
}
_retry:
handle_ = pcap_open_live(device_.toAscii().constData(), 65535,
PCAP_OPENFLAG_PROMISCUOUS, 1000 /* ms */, errbuf);
flag, 1000 /* ms */, errbuf);
if (handle_ == NULL)
{
qDebug("Error opening port %s: %s\n",
device_.toAscii().constData(), pcap_geterr(handle_));
return;
if (flag && QString(errbuf).contains("promiscuous"))
{
qDebug("%s:can't set promiscuous mode, trying non-promisc",
device_.toAscii().constData());
flag = 0;
goto _retry;
}
else
{
qDebug("%s: Error opening port %s: %s\n", __FUNCTION__,
device_.toAscii().constData(), errbuf);
return;
}
}
dumpHandle_ = pcap_dump_open(handle_,

View File

@ -43,18 +43,27 @@ PortManager::PortManager()
{
AbstractPort *port;
qDebug("%d. %s", i, device->name);
if (device->description)
qDebug(" (%s)\n", device->description);
#ifdef Q_OS_WIN32
port = new WinPcapPort(i, device->name);
#else
port = new PcapPort(i, device->name);
#endif
if (!port->isUsable())
{
qDebug("%s: unable to open %s. Skipping!", __FUNCTION__,
device->name);
delete port;
i--;
continue;
}
port->init();
portList_.append(port);
qDebug("%d. %s", i, device->name);
if (device->description)
qDebug(" (%s)\n", device->description);
}
pcap_freealldevs(deviceList);

View File

@ -124,7 +124,8 @@ WinPcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
AbstractPort::PortStats *stats)
: PcapPort::PortMonitor(device, direction, stats)
{
pcap_setmode(handle(), MODE_STAT);
if (handle())
pcap_setmode(handle(), MODE_STAT);
}
void WinPcapPort::PortMonitor::run()

View File

@ -5,6 +5,8 @@ INCLUDEPATH += "../rpc/" "../common/"
LIBS += -L"../common/debug" -lostproto
LIBS += -lprotobuf
LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
POST_TARGETDEPS += "../common/debug/libostproto.a"
HEADERS +=
SOURCES += main.cpp